foxes 1.5.1__py3-none-any.whl → 1.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/input/yaml/windio/read_attributes.py +8 -2
- foxes/input/yaml/windio/read_farm.py +20 -0
- foxes/input/yaml/windio/read_fields.py +3 -0
- foxes/input/yaml/windio/read_outputs.py +24 -12
- foxes/input/yaml/windio/read_site.py +33 -12
- foxes/input/yaml/windio/windio.py +1 -0
- foxes/models/farm_controllers/__init__.py +1 -0
- foxes/models/farm_controllers/op_flag.py +196 -0
- foxes/models/wake_models/induction/self_similar.py +22 -4
- foxes/models/wake_models/induction/self_similar2020.py +1 -1
- foxes/models/wake_models/ti/crespo_hernandez.py +1 -1
- foxes/models/wake_models/wind/bastankhah14.py +1 -1
- foxes/models/wake_models/wind/bastankhah16.py +1 -1
- foxes/models/wake_models/wind/turbopark.py +1 -1
- foxes/output/state_turbine_map.py +7 -4
- foxes/variables.py +8 -3
- {foxes-1.5.1.dist-info → foxes-1.5.2.dist-info}/METADATA +5 -6
- {foxes-1.5.1.dist-info → foxes-1.5.2.dist-info}/RECORD +23 -21
- tests/2_models/turbine_models/test_set_farm_vars.py +64 -0
- {foxes-1.5.1.dist-info → foxes-1.5.2.dist-info}/WHEEL +0 -0
- {foxes-1.5.1.dist-info → foxes-1.5.2.dist-info}/entry_points.txt +0 -0
- {foxes-1.5.1.dist-info → foxes-1.5.2.dist-info}/licenses/LICENSE +0 -0
- {foxes-1.5.1.dist-info → foxes-1.5.2.dist-info}/top_level.txt +0 -0
|
@@ -167,7 +167,13 @@ def _read_blockage(blockage_model, induction, algo_dict, mbook, verbosity):
|
|
|
167
167
|
print(" Name:", wname)
|
|
168
168
|
print(" Contents:", [k for k in blockage_model.keys()])
|
|
169
169
|
if wname not in ["None", "none"]:
|
|
170
|
-
|
|
170
|
+
kys = list(blockage_model.keys())
|
|
171
|
+
for k in kys:
|
|
172
|
+
if len(k) > 3 and k[:3] == "ss_":
|
|
173
|
+
blockage_model[k[3:]] = blockage_model.pop_item(k)
|
|
174
|
+
indc_dict = Dict(
|
|
175
|
+
wmodel_type=indc_def_map[wname], induction=induction, **blockage_model
|
|
176
|
+
)
|
|
171
177
|
mbook.wake_models[wname] = WakeModel.new(**indc_dict)
|
|
172
178
|
if verbosity > 2:
|
|
173
179
|
print(f" Created wake model '{wname}':")
|
|
@@ -378,7 +384,7 @@ def read_attributes(wio_attrs, idict, mbook, verbosity=1):
|
|
|
378
384
|
print(" Reading flow_model")
|
|
379
385
|
print(" Name:", fmname)
|
|
380
386
|
print(" Contents:", [k for k in flow_model.keys()])
|
|
381
|
-
if fmname != "foxes":
|
|
387
|
+
if verbosity > 0 and fmname != "foxes":
|
|
382
388
|
print(f"Running flow model 'foxes', overruling original choice '{fmname}'")
|
|
383
389
|
|
|
384
390
|
# read analysis:
|
|
@@ -3,7 +3,9 @@ import pandas as pd
|
|
|
3
3
|
|
|
4
4
|
from foxes.utils import Dict
|
|
5
5
|
from foxes.core import Turbine, TurbineType, WindFarm
|
|
6
|
+
from foxes.models.farm_controllers import BasicFarmController, OpFlagController
|
|
6
7
|
import foxes.variables as FV
|
|
8
|
+
import foxes.constants as FC
|
|
7
9
|
|
|
8
10
|
|
|
9
11
|
def read_turbine_types(wio_farm, mbook, ws_exp_P, ws_exp_ct, verbosity):
|
|
@@ -204,6 +206,22 @@ def read_farm(wio_dict, mbook, verbosity):
|
|
|
204
206
|
ws_exp_P = 1
|
|
205
207
|
ws_exp_ct = 1
|
|
206
208
|
|
|
209
|
+
# create farm controller:
|
|
210
|
+
if FV.OPERATING in wio_farm:
|
|
211
|
+
op_dims, operating = wio_farm.pop_item(FV.OPERATING)
|
|
212
|
+
assert (
|
|
213
|
+
len(op_dims) == 2
|
|
214
|
+
and op_dims[1] == FC.TURBINE
|
|
215
|
+
and op_dims[0] in [FC.STATE, FC.TIME]
|
|
216
|
+
), f"Expecting operating field to have dims (state, turbine), got {op_dims}"
|
|
217
|
+
mbook.farm_controllers["farm_cntrl"] = OpFlagController(operating)
|
|
218
|
+
else:
|
|
219
|
+
mbook.farm_controllers["farm_cntrl"] = BasicFarmController()
|
|
220
|
+
if verbosity > 1:
|
|
221
|
+
print(
|
|
222
|
+
f" Farm controller type: {type(mbook.farm_controllers['farm_cntrl']).__name__}"
|
|
223
|
+
)
|
|
224
|
+
|
|
207
225
|
# read turbine type:
|
|
208
226
|
ttypes = read_turbine_types(wio_farm, mbook, ws_exp_P, ws_exp_ct, verbosity)
|
|
209
227
|
|
|
@@ -211,6 +229,8 @@ def read_farm(wio_dict, mbook, verbosity):
|
|
|
211
229
|
farm = WindFarm()
|
|
212
230
|
wfarm = wio_farm["layouts"]
|
|
213
231
|
if isinstance(wfarm, dict):
|
|
232
|
+
if "coordinates" in wfarm:
|
|
233
|
+
wfarm = {"0": wfarm}
|
|
214
234
|
layouts = Dict(wfarm, _name=wio_farm.name + ".layouts")
|
|
215
235
|
else:
|
|
216
236
|
layouts = {str(i): lf for i, lf in enumerate(wfarm)}
|
|
@@ -24,6 +24,7 @@ wio2foxes = {
|
|
|
24
24
|
"reference_height": FV.H,
|
|
25
25
|
"weibull_a": FV.WEIBULL_A,
|
|
26
26
|
"weibull_k": FV.WEIBULL_k,
|
|
27
|
+
"operating": FV.OPERATING,
|
|
27
28
|
}
|
|
28
29
|
|
|
29
30
|
""" Mapping from foxes to windio variables
|
|
@@ -137,6 +138,7 @@ def read_wind_resource_field(
|
|
|
137
138
|
"""
|
|
138
139
|
if name in [
|
|
139
140
|
"potential_temperature",
|
|
141
|
+
"real_temperature",
|
|
140
142
|
"friction_velocity",
|
|
141
143
|
"k",
|
|
142
144
|
"epsilon",
|
|
@@ -180,6 +182,7 @@ def read_wind_resource_field(
|
|
|
180
182
|
"reference_height",
|
|
181
183
|
"weibull_a",
|
|
182
184
|
"weibull_k",
|
|
185
|
+
"operating",
|
|
183
186
|
] and _read_multi_dimensional_data(name, wio_data, fields, dims):
|
|
184
187
|
return True
|
|
185
188
|
|
|
@@ -110,14 +110,28 @@ def _read_flow_field(wio_outs, olist, algo, states_isel, verbosity):
|
|
|
110
110
|
assert len(xb) == 2, f"Expecting two entries for x_bounds, got {xb}"
|
|
111
111
|
yb = z_planes.pop_item("y_bounds")
|
|
112
112
|
assert len(yb) == 2, f"Expecting two entries for y_bounds, got {yb}"
|
|
113
|
-
dx
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
113
|
+
if "dx" in z_planes or "dy" in z_planes:
|
|
114
|
+
assert "dx" in z_planes and "dy" in z_planes, (
|
|
115
|
+
f"Expecting both 'dx' and 'dy' in z_planes, got {list(z_planes.keys())}"
|
|
116
|
+
)
|
|
117
|
+
dx = z_planes.pop_item("dx")
|
|
118
|
+
dy = z_planes.pop_item("dy")
|
|
119
|
+
nx = max(int((xb[1] - xb[0]) / dx), 1) + 1
|
|
120
|
+
if (xb[1] - xb[0]) / (nx - 1) > dx:
|
|
121
|
+
nx += 1
|
|
122
|
+
ny = max(int((yb[1] - yb[0]) / dy), 1) + 1
|
|
123
|
+
if (yb[1] - yb[0]) / (ny - 1) > dy:
|
|
124
|
+
ny += 1
|
|
125
|
+
elif "Nx" in z_planes or "Ny" in z_planes:
|
|
126
|
+
assert "Nx" in z_planes and "Ny" in z_planes, (
|
|
127
|
+
f"Expecting both 'Nx' and 'Ny' in z_planes, got {list(z_planes.keys())}"
|
|
128
|
+
)
|
|
129
|
+
nx = z_planes.pop_item("Nx")
|
|
130
|
+
ny = z_planes.pop_item("Ny")
|
|
131
|
+
else:
|
|
132
|
+
raise KeyError(
|
|
133
|
+
f"Expecting either 'dx' and 'dy' or 'Nx' and 'Ny' in z_planes, got {list(z_planes.keys())}"
|
|
134
|
+
)
|
|
121
135
|
z_list = np.asarray(z_list)
|
|
122
136
|
if verbosity > 2:
|
|
123
137
|
print(" x_bounds :", xb)
|
|
@@ -186,11 +200,10 @@ def read_outputs(wio_outs, idict, algo, verbosity=1):
|
|
|
186
200
|
|
|
187
201
|
# read subset:
|
|
188
202
|
run_configuration = wio_outs.pop_item("run_configuration", {})
|
|
203
|
+
states_isel = None
|
|
189
204
|
if "times_run" in run_configuration:
|
|
190
205
|
times_run = run_configuration.pop_item("times_run")
|
|
191
|
-
if times_run.get_item("all_occurences"):
|
|
192
|
-
states_isel = None
|
|
193
|
-
else:
|
|
206
|
+
if not times_run.get_item("all_occurences"):
|
|
194
207
|
states_isel = times_run.get_item("subset")
|
|
195
208
|
elif "wind_speeds_run" in run_configuration:
|
|
196
209
|
wind_speeds_run = run_configuration.get_item("wind_speeds_run")
|
|
@@ -203,7 +216,6 @@ def read_outputs(wio_outs, idict, algo, verbosity=1):
|
|
|
203
216
|
raise NotImplementedError(
|
|
204
217
|
f"Wind speed and direction subsets are not yet supported, got {directions_run.name} {directions_run}"
|
|
205
218
|
)
|
|
206
|
-
states_isel = None
|
|
207
219
|
|
|
208
220
|
# read turbine_outputs:
|
|
209
221
|
_read_turbine_outputs(wio_outs, olist, algo, states_isel, verbosity)
|
|
@@ -11,6 +11,14 @@ import foxes.constants as FC
|
|
|
11
11
|
from .read_fields import read_wind_resource_field
|
|
12
12
|
|
|
13
13
|
|
|
14
|
+
default_values = {
|
|
15
|
+
FV.WS: 8.0,
|
|
16
|
+
FV.WD: 270.0,
|
|
17
|
+
FV.TI: 0.1,
|
|
18
|
+
FV.RHO: 1.225,
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
|
|
14
22
|
def _get_profiles(coords, fields, dims, ovars, fixval, verbosity):
|
|
15
23
|
"""Read ABL profiles information
|
|
16
24
|
:group: input.yaml.windio
|
|
@@ -22,6 +30,8 @@ def _get_profiles(coords, fields, dims, ovars, fixval, verbosity):
|
|
|
22
30
|
print(
|
|
23
31
|
f"Ignoring '{FV.Z0}', since no reference_height found. No ABL profile activated."
|
|
24
32
|
)
|
|
33
|
+
fields.pop(FV.Z0)
|
|
34
|
+
dims.pop(FV.Z0)
|
|
25
35
|
elif FV.MOL in fields:
|
|
26
36
|
ovars.append(FV.MOL)
|
|
27
37
|
fixval[FV.H] = fields[FV.H]
|
|
@@ -56,7 +66,7 @@ def _get_SingleStateStates(
|
|
|
56
66
|
|
|
57
67
|
smap = {FV.WS: "ws", FV.WD: "wd", FV.TI: "ti", FV.RHO: "rho"}
|
|
58
68
|
|
|
59
|
-
data = {smap[v]:
|
|
69
|
+
data = {smap[v]: fixval.get(v, default_values[v]) for v in ovars}
|
|
60
70
|
for v, d in coords.items():
|
|
61
71
|
if v in smap:
|
|
62
72
|
data[smap[v]] = d
|
|
@@ -91,7 +101,7 @@ def _get_Timeseries(
|
|
|
91
101
|
print(" selecting class 'Timeseries'")
|
|
92
102
|
|
|
93
103
|
data = {}
|
|
94
|
-
fix = {}
|
|
104
|
+
fix = {v: fixval.get(v, default_values[v]) for v in ovars if v not in fields}
|
|
95
105
|
for v, d in fields.items():
|
|
96
106
|
if dims[v] == (FC.TIME,):
|
|
97
107
|
data[v] = d
|
|
@@ -99,7 +109,6 @@ def _get_Timeseries(
|
|
|
99
109
|
fix[v] = d
|
|
100
110
|
elif verbosity > 2:
|
|
101
111
|
print(f" ignoring field '{v}' with dims {dims[v]}")
|
|
102
|
-
fix.update({v: d for v, d in fixval.items() if v not in data})
|
|
103
112
|
|
|
104
113
|
sdata = pd.DataFrame(index=coords[FC.TIME], data=data)
|
|
105
114
|
sdata.index.name = FC.TIME
|
|
@@ -132,7 +141,7 @@ def _get_MultiHeightNCTimeseries(
|
|
|
132
141
|
)
|
|
133
142
|
|
|
134
143
|
data = {}
|
|
135
|
-
fix = {}
|
|
144
|
+
fix = {v: fixval.get(v, default_values[v]) for v in ovars if v not in fields}
|
|
136
145
|
for v, d in fields.items():
|
|
137
146
|
if dims[v] == (FC.TIME, FV.H):
|
|
138
147
|
data[v] = ((FC.TIME, FV.H), d)
|
|
@@ -142,7 +151,6 @@ def _get_MultiHeightNCTimeseries(
|
|
|
142
151
|
fix[v] = d
|
|
143
152
|
elif verbosity > 2:
|
|
144
153
|
print(f" ignoring field '{v}' with dims {dims[v]}")
|
|
145
|
-
fix.update({v: d for v, d in fixval.items() if v not in data})
|
|
146
154
|
|
|
147
155
|
sdata = Dataset(coords=coords, data_vars=data)
|
|
148
156
|
states_dict.update(
|
|
@@ -153,6 +161,7 @@ def _get_MultiHeightNCTimeseries(
|
|
|
153
161
|
data_source=sdata,
|
|
154
162
|
output_vars=ovars,
|
|
155
163
|
fixed_vars=fix,
|
|
164
|
+
bounds_error=False,
|
|
156
165
|
)
|
|
157
166
|
)
|
|
158
167
|
return True
|
|
@@ -177,7 +186,7 @@ def _get_WeibullSectors(
|
|
|
177
186
|
print(" selecting class 'WeibullSectors'")
|
|
178
187
|
|
|
179
188
|
data = {}
|
|
180
|
-
fix = {}
|
|
189
|
+
fix = {v: fixval.get(v, default_values[v]) for v in ovars if v not in fields}
|
|
181
190
|
c = dims[FV.WEIBULL_A][0]
|
|
182
191
|
for v, d in fields.items():
|
|
183
192
|
if dims[v] == (c,):
|
|
@@ -186,7 +195,6 @@ def _get_WeibullSectors(
|
|
|
186
195
|
fix[v] = d
|
|
187
196
|
elif verbosity > 2:
|
|
188
197
|
print(f" ignoring field '{v}' with dims {dims[v]}")
|
|
189
|
-
fix.update({v: d for v, d in fixval.items() if v not in data})
|
|
190
198
|
|
|
191
199
|
if FV.WD in coords:
|
|
192
200
|
data[FV.WD] = coords[FV.WD]
|
|
@@ -230,13 +238,12 @@ def _get_WeibullPointCloud(
|
|
|
230
238
|
print(" selecting class 'WeibullPointCloud'")
|
|
231
239
|
|
|
232
240
|
data = {}
|
|
233
|
-
fix = {}
|
|
241
|
+
fix = {v: fixval.get(v, default_values[v]) for v in ovars if v not in fields}
|
|
234
242
|
for v, d in fields.items():
|
|
235
243
|
if len(dims[v]) == 0:
|
|
236
244
|
fix[v] = d
|
|
237
245
|
elif v not in fixval:
|
|
238
246
|
data[v] = (dims[v], d)
|
|
239
|
-
fix.update({v: d for v, d in fixval.items() if v not in data})
|
|
240
247
|
|
|
241
248
|
sdata = Dataset(
|
|
242
249
|
coords=coords,
|
|
@@ -282,13 +289,12 @@ def _get_WeibullField(
|
|
|
282
289
|
print(" selecting class 'WeibullField'")
|
|
283
290
|
|
|
284
291
|
data = {}
|
|
285
|
-
fix = {}
|
|
292
|
+
fix = {v: fixval.get(v, default_values[v]) for v in ovars if v not in fields}
|
|
286
293
|
for v, d in fields.items():
|
|
287
294
|
if len(dims[v]) == 0:
|
|
288
295
|
fix[v] = d
|
|
289
296
|
elif v not in fixval:
|
|
290
297
|
data[v] = (dims[v], d)
|
|
291
|
-
fix.update({v: d for v, d in fixval.items() if v not in data})
|
|
292
298
|
|
|
293
299
|
sdata = Dataset(
|
|
294
300
|
coords=coords,
|
|
@@ -342,7 +348,7 @@ def get_states(coords, fields, dims, verbosity=1):
|
|
|
342
348
|
print(" Creating states")
|
|
343
349
|
|
|
344
350
|
ovars = [FV.WS, FV.WD, FV.TI, FV.RHO]
|
|
345
|
-
fixval = {
|
|
351
|
+
fixval = {}
|
|
346
352
|
profiles = _get_profiles(coords, fields, dims, ovars, fixval, verbosity)
|
|
347
353
|
|
|
348
354
|
states_dict = {}
|
|
@@ -421,6 +427,21 @@ def read_site(wio_dict, verbosity=1):
|
|
|
421
427
|
dims = Dict(_name="dims")
|
|
422
428
|
for n, d in wind_resource.items():
|
|
423
429
|
read_wind_resource_field(n, d, coords, fields, dims, verbosity)
|
|
430
|
+
|
|
431
|
+
# special case: operating field
|
|
432
|
+
if FV.OPERATING in fields:
|
|
433
|
+
wio_dict["wind_farm"][FV.OPERATING] = (
|
|
434
|
+
dims.pop(FV.OPERATING),
|
|
435
|
+
fields.pop(FV.OPERATING),
|
|
436
|
+
)
|
|
437
|
+
if FC.TURBINE in coords:
|
|
438
|
+
if not any([FC.TURBINE in dms for dms in dims.values()]):
|
|
439
|
+
if verbosity > 2:
|
|
440
|
+
print(
|
|
441
|
+
f" Removing coordinate '{FC.TURBINE}', since only relevant for operating flag"
|
|
442
|
+
)
|
|
443
|
+
coords.pop(FC.TURBINE)
|
|
444
|
+
|
|
424
445
|
if verbosity > 2:
|
|
425
446
|
print(" Coords:")
|
|
426
447
|
for c, d in coords.items():
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
from xarray import open_dataset, Dataset
|
|
3
|
+
|
|
4
|
+
from foxes.core import FarmController
|
|
5
|
+
import foxes.constants as FC
|
|
6
|
+
import foxes.variables as FV
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class OpFlagController(FarmController):
|
|
10
|
+
"""
|
|
11
|
+
A basic controller with a flag for
|
|
12
|
+
turbine operation at each state.
|
|
13
|
+
|
|
14
|
+
Parameters
|
|
15
|
+
----------
|
|
16
|
+
non_op_values: dict
|
|
17
|
+
The non-operational values for variables,
|
|
18
|
+
keys: variable str, values: float
|
|
19
|
+
var2ncvar: dict
|
|
20
|
+
The mapping of variable names to NetCDF variable names,
|
|
21
|
+
only needed if data_source is a path to a NetCDF file
|
|
22
|
+
|
|
23
|
+
:group: models.farm_controllers
|
|
24
|
+
|
|
25
|
+
"""
|
|
26
|
+
|
|
27
|
+
def __init__(
|
|
28
|
+
self,
|
|
29
|
+
data_source,
|
|
30
|
+
non_op_values=None,
|
|
31
|
+
var2ncvar={},
|
|
32
|
+
**kwargs,
|
|
33
|
+
):
|
|
34
|
+
"""
|
|
35
|
+
Constructor.
|
|
36
|
+
|
|
37
|
+
Parameters
|
|
38
|
+
----------
|
|
39
|
+
data_source: numpy.ndarray or str
|
|
40
|
+
The operating flag data, shape: (n_states, n_turbines),
|
|
41
|
+
or path to a NetCDF file
|
|
42
|
+
non_op_values: dict, optional
|
|
43
|
+
The non-operational values for variables,
|
|
44
|
+
keys: variable str, values: float
|
|
45
|
+
var2ncvar: dict
|
|
46
|
+
The mapping of variable names to NetCDF variable names,
|
|
47
|
+
only needed if data_source is a path to a NetCDF file
|
|
48
|
+
kwargs: dict, optional
|
|
49
|
+
Additional keyword arguments for the
|
|
50
|
+
base class constructor
|
|
51
|
+
|
|
52
|
+
"""
|
|
53
|
+
super().__init__(**kwargs)
|
|
54
|
+
self.data_source = data_source
|
|
55
|
+
self.var2ncvar = var2ncvar
|
|
56
|
+
|
|
57
|
+
self.non_op_values = {
|
|
58
|
+
FV.P: 0.0,
|
|
59
|
+
FV.CT: 0.0,
|
|
60
|
+
}
|
|
61
|
+
if non_op_values is not None:
|
|
62
|
+
self.non_op_values.update(non_op_values)
|
|
63
|
+
|
|
64
|
+
self._op_flags = None
|
|
65
|
+
|
|
66
|
+
def output_farm_vars(self, algo):
|
|
67
|
+
"""
|
|
68
|
+
The variables which are being modified by the model.
|
|
69
|
+
|
|
70
|
+
Parameters
|
|
71
|
+
----------
|
|
72
|
+
algo: foxes.core.Algorithm
|
|
73
|
+
The calculation algorithm
|
|
74
|
+
|
|
75
|
+
Returns
|
|
76
|
+
-------
|
|
77
|
+
output_vars: list of str
|
|
78
|
+
The output variable names
|
|
79
|
+
|
|
80
|
+
"""
|
|
81
|
+
vrs = set(super().output_farm_vars(algo))
|
|
82
|
+
vrs.update([FV.OPERATING])
|
|
83
|
+
return list(vrs)
|
|
84
|
+
|
|
85
|
+
def load_data(self, algo, verbosity=0):
|
|
86
|
+
"""
|
|
87
|
+
Load and/or create all model data that is subject to chunking.
|
|
88
|
+
|
|
89
|
+
Such data should not be stored under self, for memory reasons. The
|
|
90
|
+
data returned here will automatically be chunked and then provided
|
|
91
|
+
as part of the mdata object during calculations.
|
|
92
|
+
|
|
93
|
+
Parameters
|
|
94
|
+
----------
|
|
95
|
+
algo: foxes.core.Algorithm
|
|
96
|
+
The calculation algorithm
|
|
97
|
+
verbosity: int
|
|
98
|
+
The verbosity level, 0 = silent
|
|
99
|
+
|
|
100
|
+
Returns
|
|
101
|
+
-------
|
|
102
|
+
idata: dict
|
|
103
|
+
The dict has exactly two entries: `data_vars`,
|
|
104
|
+
a dict with entries `name_str -> (dim_tuple, data_ndarray)`;
|
|
105
|
+
and `coords`, a dict with entries `dim_name_str -> dim_array`
|
|
106
|
+
|
|
107
|
+
"""
|
|
108
|
+
|
|
109
|
+
idata = super().load_data(algo, verbosity)
|
|
110
|
+
|
|
111
|
+
if isinstance(self.data_source, np.ndarray):
|
|
112
|
+
self._op_flags = self.data_source
|
|
113
|
+
|
|
114
|
+
elif isinstance(self.data_source, Dataset):
|
|
115
|
+
cop = self.var2ncvar.get(FV.OPERATING, FV.OPERATING)
|
|
116
|
+
self._op_flags = self.data_source[cop].to_numpy()
|
|
117
|
+
|
|
118
|
+
else:
|
|
119
|
+
if verbosity > 0:
|
|
120
|
+
print(f"OpFlagController: Reading data from {self.data_source}")
|
|
121
|
+
ds = open_dataset(self.data_source)
|
|
122
|
+
cop = self.var2ncvar.get(FV.OPERATING, FV.OPERATING)
|
|
123
|
+
self._op_flags = ds[cop].to_numpy()
|
|
124
|
+
del ds
|
|
125
|
+
|
|
126
|
+
assert self._op_flags.shape == (algo.n_states, algo.n_turbines), (
|
|
127
|
+
f"OpFlagController data shape {self._op_flags.shape} does not match "
|
|
128
|
+
f"(n_states, n_turbines)=({algo.n_states}, {algo.n_turbines})"
|
|
129
|
+
)
|
|
130
|
+
op_flags = self._op_flags.astype(bool)
|
|
131
|
+
|
|
132
|
+
off = np.where(~op_flags)
|
|
133
|
+
tmsels = idata["data_vars"][FC.TMODEL_SELS][1]
|
|
134
|
+
tmsels[off[0], off[1], :] = False
|
|
135
|
+
self._tmall = [np.all(t) for t in tmsels]
|
|
136
|
+
|
|
137
|
+
idata["data_vars"][FC.TMODEL_SELS] = (
|
|
138
|
+
(FC.STATE, FC.TURBINE, FC.TMODELS),
|
|
139
|
+
tmsels,
|
|
140
|
+
)
|
|
141
|
+
idata["data_vars"][FV.OPERATING] = (
|
|
142
|
+
(FC.STATE, FC.TURBINE),
|
|
143
|
+
op_flags,
|
|
144
|
+
)
|
|
145
|
+
|
|
146
|
+
return idata
|
|
147
|
+
|
|
148
|
+
def calculate(self, algo, mdata, fdata, pre_rotor, downwind_index=None):
|
|
149
|
+
"""
|
|
150
|
+
The main model calculation.
|
|
151
|
+
|
|
152
|
+
This function is executed on a single chunk of data,
|
|
153
|
+
all computations should be based on numpy arrays.
|
|
154
|
+
|
|
155
|
+
Parameters
|
|
156
|
+
----------
|
|
157
|
+
algo: foxes.core.Algorithm
|
|
158
|
+
The calculation algorithm
|
|
159
|
+
mdata: foxes.core.MData
|
|
160
|
+
The model data
|
|
161
|
+
fdata: foxes.core.FData
|
|
162
|
+
The farm data
|
|
163
|
+
pre_rotor: bool
|
|
164
|
+
Flag for running pre-rotor or post-rotor
|
|
165
|
+
models
|
|
166
|
+
downwind_index: int, optional
|
|
167
|
+
The index in the downwind order
|
|
168
|
+
|
|
169
|
+
Returns
|
|
170
|
+
-------
|
|
171
|
+
results: dict
|
|
172
|
+
The resulting data, keys: output variable str.
|
|
173
|
+
Values: numpy.ndarray with shape (n_states, n_turbines)
|
|
174
|
+
|
|
175
|
+
"""
|
|
176
|
+
self.ensure_output_vars(algo, fdata)
|
|
177
|
+
|
|
178
|
+
# compute data for all operating turbines:
|
|
179
|
+
op = mdata[FV.OPERATING].astype(bool)
|
|
180
|
+
fdata[FV.OPERATING] = op
|
|
181
|
+
results = super().calculate(algo, mdata, fdata, pre_rotor, downwind_index)
|
|
182
|
+
results[FV.OPERATING] = fdata[FV.OPERATING]
|
|
183
|
+
|
|
184
|
+
# set non-operating values:
|
|
185
|
+
if downwind_index is None:
|
|
186
|
+
off = np.where(~op)
|
|
187
|
+
for v in self.output_farm_vars(algo):
|
|
188
|
+
if v != FV.OPERATING:
|
|
189
|
+
fdata[v][off[0], off[1]] = self.non_op_values.get(v, np.nan)
|
|
190
|
+
else:
|
|
191
|
+
off = np.where(~op[:, downwind_index])
|
|
192
|
+
for v in self.output_farm_vars(algo):
|
|
193
|
+
if v != FV.OPERATING:
|
|
194
|
+
fdata[v][off[0], downwind_index] = self.non_op_values.get(v, np.nan)
|
|
195
|
+
|
|
196
|
+
return results
|
|
@@ -27,6 +27,12 @@ class SelfSimilar(TurbineInductionModel):
|
|
|
27
27
|
|
|
28
28
|
Attributes
|
|
29
29
|
----------
|
|
30
|
+
alpha: float
|
|
31
|
+
The alpha parameter
|
|
32
|
+
beta: float
|
|
33
|
+
The beta parameter
|
|
34
|
+
gamma: float
|
|
35
|
+
The gamma parameter
|
|
30
36
|
pre_rotor_only: bool
|
|
31
37
|
Calculate only the pre-rotor region
|
|
32
38
|
induction: foxes.core.AxialInductionModel or str
|
|
@@ -40,6 +46,8 @@ class SelfSimilar(TurbineInductionModel):
|
|
|
40
46
|
self,
|
|
41
47
|
superposition="ws_linear",
|
|
42
48
|
induction="Madsen",
|
|
49
|
+
alpha=8 / 9,
|
|
50
|
+
beta=np.sqrt(2),
|
|
43
51
|
gamma=1.1,
|
|
44
52
|
pre_rotor_only=False,
|
|
45
53
|
):
|
|
@@ -52,8 +60,12 @@ class SelfSimilar(TurbineInductionModel):
|
|
|
52
60
|
The wind speed superposition.
|
|
53
61
|
induction: foxes.core.AxialInductionModel or str
|
|
54
62
|
The induction model
|
|
55
|
-
|
|
56
|
-
The parameter
|
|
63
|
+
alpha: float
|
|
64
|
+
The alpha parameter
|
|
65
|
+
beta: float
|
|
66
|
+
The beta parameter
|
|
67
|
+
gamma: float
|
|
68
|
+
The gamma parameter
|
|
57
69
|
pre_rotor_only: bool
|
|
58
70
|
Calculate only the pre-rotor region
|
|
59
71
|
|
|
@@ -61,6 +73,8 @@ class SelfSimilar(TurbineInductionModel):
|
|
|
61
73
|
super().__init__(wind_superposition=superposition)
|
|
62
74
|
self.induction = induction
|
|
63
75
|
self.pre_rotor_only = pre_rotor_only
|
|
76
|
+
self.alpha = alpha
|
|
77
|
+
self.beta = beta
|
|
64
78
|
self.gamma = gamma
|
|
65
79
|
|
|
66
80
|
def __repr__(self):
|
|
@@ -163,9 +177,13 @@ class SelfSimilar(TurbineInductionModel):
|
|
|
163
177
|
"""Helper function: using eqn 13 from [2]"""
|
|
164
178
|
return np.sqrt(0.587 * (1.32 + x_R**2))
|
|
165
179
|
|
|
166
|
-
def _rad_fn(self, x_R, r_R
|
|
180
|
+
def _rad_fn(self, x_R, r_R):
|
|
167
181
|
"""Helper function: define radial shape function (eqn 12 from [1])"""
|
|
168
|
-
|
|
182
|
+
with np.errstate(over="ignore"):
|
|
183
|
+
result = (
|
|
184
|
+
1 / np.cosh(self.beta * (r_R) / self._r_half(x_R))
|
|
185
|
+
) ** self.alpha # * (x_R < 0)
|
|
186
|
+
return result
|
|
169
187
|
|
|
170
188
|
def contribute(
|
|
171
189
|
self,
|
|
@@ -218,7 +218,7 @@ class CrespoHernandezTIWake(TopHatWakeModel):
|
|
|
218
218
|
|
|
219
219
|
# calculate:
|
|
220
220
|
a = self.induction.ct2a(ct)
|
|
221
|
-
beta = (1 - a) / (1 - 2 * a)
|
|
221
|
+
beta = np.maximum((1 - a) / (1 - 2 * a), 0)
|
|
222
222
|
radius = 2 * (k * x + self.sbeta_factor * np.sqrt(beta) * D)
|
|
223
223
|
|
|
224
224
|
return radius
|
|
@@ -194,7 +194,7 @@ class Bastankhah2014(GaussianWakeModel):
|
|
|
194
194
|
# calculate sigma:
|
|
195
195
|
# beta = 0.5 * (1 + np.sqrt(1.0 - ct)) / np.sqrt(1.0 - ct)
|
|
196
196
|
a = self.induction.ct2a(ct)
|
|
197
|
-
beta = (1 - a) / (1 - 2 * a)
|
|
197
|
+
beta = np.maximum((1 - a) / (1 - 2 * a), 0)
|
|
198
198
|
sigma = k * x + self.sbeta_factor * np.sqrt(beta) * D
|
|
199
199
|
del beta, a
|
|
200
200
|
|
|
@@ -220,7 +220,7 @@ class TurbOParkWake(GaussianWakeModel):
|
|
|
220
220
|
# calculate sigma:
|
|
221
221
|
# beta = np.sqrt(0.5 * (1 + np.sqrt(1.0 - ct)) / np.sqrt(1.0 - ct))
|
|
222
222
|
a = self.induction.ct2a(ct)
|
|
223
|
-
beta = (1 - a) / (1 - 2 * a)
|
|
223
|
+
beta = np.maximum((1 - a) / (1 - 2 * a), 0)
|
|
224
224
|
epsilon = self.sbeta_factor * np.sqrt(beta)
|
|
225
225
|
del a, beta
|
|
226
226
|
|
|
@@ -39,6 +39,7 @@ class StateTurbineMap(Output):
|
|
|
39
39
|
self,
|
|
40
40
|
variable,
|
|
41
41
|
title=None,
|
|
42
|
+
cbar_label=None,
|
|
42
43
|
ax=None,
|
|
43
44
|
figsize=None,
|
|
44
45
|
rotate_xlabels=None,
|
|
@@ -93,8 +94,11 @@ class StateTurbineMap(Output):
|
|
|
93
94
|
|
|
94
95
|
ax.set_yticks(turbines[:-1] + 0.5)
|
|
95
96
|
ax.set_yticklabels(turbines[:-1])
|
|
96
|
-
xt = ax.get_xticks()
|
|
97
|
+
xt = np.asarray(ax.get_xticks())
|
|
97
98
|
xtl = ax.get_xticklabels()
|
|
99
|
+
if xt.dtype != np.datetime64:
|
|
100
|
+
xt, ar = np.unique(xt.astype(int), return_index=True)
|
|
101
|
+
xtl = [int(float(xtl[i].get_text())) for i in ar]
|
|
98
102
|
ax.set_xticks(
|
|
99
103
|
xt[:-1] + 0.5 * (xt[-1] - xt[-2]), xtl[:-1], rotation=rotate_xlabels
|
|
100
104
|
)
|
|
@@ -103,10 +107,9 @@ class StateTurbineMap(Output):
|
|
|
103
107
|
ytl = [None for t in yt]
|
|
104
108
|
ytl[::5] = ax.get_yticklabels()[::5]
|
|
105
109
|
ax.set_yticks(yt, ytl)
|
|
106
|
-
fig.colorbar(c, ax=ax)
|
|
110
|
+
fig.colorbar(c, ax=ax, label=cbar_label)
|
|
107
111
|
|
|
108
|
-
|
|
109
|
-
ax.set_title(t)
|
|
112
|
+
ax.set_title(title)
|
|
110
113
|
ax.set_ylabel("Turbine index")
|
|
111
114
|
ax.set_xlabel("State")
|
|
112
115
|
|
foxes/variables.py
CHANGED
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
OPERATING = "operating"
|
|
2
|
+
""" Flag for turbine operation
|
|
3
|
+
:group: foxes.variables
|
|
4
|
+
"""
|
|
5
|
+
|
|
1
6
|
X = "X"
|
|
2
7
|
""" The x coordinate in m
|
|
3
8
|
:group: foxes.variables
|
|
@@ -19,7 +24,7 @@ D = "D"
|
|
|
19
24
|
"""
|
|
20
25
|
|
|
21
26
|
TXYH = "txyh"
|
|
22
|
-
""" The turbine rotor centre coordinate
|
|
27
|
+
""" The turbine rotor centre coordinate
|
|
23
28
|
vector (x, y, height)
|
|
24
29
|
:group: foxes.variables
|
|
25
30
|
"""
|
|
@@ -190,13 +195,13 @@ AMB_RHO = "AMB_RHO"
|
|
|
190
195
|
"""
|
|
191
196
|
|
|
192
197
|
AMB_YAW = "AMB_YAW"
|
|
193
|
-
""" The ambient absolute yaw angle of
|
|
198
|
+
""" The ambient absolute yaw angle of
|
|
194
199
|
a turbine in degrees
|
|
195
200
|
:group: foxes.variables
|
|
196
201
|
"""
|
|
197
202
|
|
|
198
203
|
AMB_YAWM = "AMB_YAWM"
|
|
199
|
-
""" The ambient relative yaw angle of
|
|
204
|
+
""" The ambient relative yaw angle of
|
|
200
205
|
a turbine in degrees
|
|
201
206
|
:group: foxes.variables
|
|
202
207
|
"""
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: foxes
|
|
3
|
-
Version: 1.5.
|
|
3
|
+
Version: 1.5.2
|
|
4
4
|
Summary: Farm Optimization and eXtended yield Evaluation Software
|
|
5
5
|
Author: Jonas Schulte
|
|
6
6
|
Maintainer: Jonas Schulte
|
|
@@ -47,17 +47,16 @@ Classifier: Development Status :: 4 - Beta
|
|
|
47
47
|
Requires-Python: >=3.9
|
|
48
48
|
Description-Content-Type: text/markdown
|
|
49
49
|
License-File: LICENSE
|
|
50
|
-
Requires-Dist: cycler>=0.10
|
|
51
|
-
Requires-Dist: h5netcdf>=1.0
|
|
52
50
|
Requires-Dist: matplotlib>=3.8
|
|
53
51
|
Requires-Dist: numpy>=1.26
|
|
54
52
|
Requires-Dist: pandas>=2.0
|
|
55
|
-
Requires-Dist: pyyaml>=4.0
|
|
56
53
|
Requires-Dist: scipy>=1.12
|
|
57
|
-
Requires-Dist: tqdm>=2.0
|
|
58
54
|
Requires-Dist: xarray>=2023
|
|
55
|
+
Requires-Dist: h5netcdf>=1.0
|
|
56
|
+
Requires-Dist: pyyaml>=4.0
|
|
57
|
+
Requires-Dist: tqdm>=2.0
|
|
59
58
|
Provides-Extra: opt
|
|
60
|
-
Requires-Dist: foxes-opt>=0.
|
|
59
|
+
Requires-Dist: foxes-opt>=0.6; extra == "opt"
|
|
61
60
|
Provides-Extra: dask
|
|
62
61
|
Requires-Dist: dask>=2022.0; extra == "dask"
|
|
63
62
|
Requires-Dist: distributed>=2022.0; extra == "dask"
|
|
@@ -23,7 +23,7 @@ examples/wind_rose/run.py,sha256=CU7pzOSlWHifFvdtKl_t9gufaAKw2TkjwvklDZRaawM,438
|
|
|
23
23
|
examples/yawed_wake/run.py,sha256=X-cxmhC0rCRHyB00kXrsnqQ9fufSY7L35lozls7Nxuw,6882
|
|
24
24
|
foxes/__init__.py,sha256=1RPU7w3WJ3jFb2aJdZKRy-6Fje9qAaH85WYcOCiDvwk,1375
|
|
25
25
|
foxes/constants.py,sha256=jQcyeU53V629Tf8qQWc2F4Xw1rV3ywtJiT-g1JWenNg,3842
|
|
26
|
-
foxes/variables.py,sha256=
|
|
26
|
+
foxes/variables.py,sha256=7B5wFWUunrFZLjU2l2cgYZ5nyZmakOLR1gqh-G3BTuI,6225
|
|
27
27
|
foxes/algorithms/__init__.py,sha256=L0VyK-B81zXr-IFI6NMhJ7Px9XVhlkmX0M0IrKhcf0o,327
|
|
28
28
|
foxes/algorithms/downwind/__init__.py,sha256=tdTnMEVLi58EMkqStollQb4gPug4x8Te2K8ddAxkas8,75
|
|
29
29
|
foxes/algorithms/downwind/downwind.py,sha256=Rqpe-BYWVt8eS1HxsRYFO93SgblVxmuTKFI1sSFzhXQ,26215
|
|
@@ -135,19 +135,20 @@ foxes/input/yaml/__init__.py,sha256=XGCJlbE1SwavEWEKDRAuJwqAi9Afm_qwPnQLxPKjzP4,
|
|
|
135
135
|
foxes/input/yaml/dict.py,sha256=0hRqpF0Gn3FknS-xldyzzhKTTpYlv8GTqUBsLIFjolU,14921
|
|
136
136
|
foxes/input/yaml/yaml.py,sha256=0hikKGhkjipYANJNeXgNZ8xzVj-mMscmsA26w_6HdgE,2741
|
|
137
137
|
foxes/input/yaml/windio/__init__.py,sha256=HXJEBEDd1FbATkDfjXzA3sgo9detUxgvekmC32QOc5E,446
|
|
138
|
-
foxes/input/yaml/windio/read_attributes.py,sha256=
|
|
139
|
-
foxes/input/yaml/windio/read_farm.py,sha256=
|
|
140
|
-
foxes/input/yaml/windio/read_fields.py,sha256=
|
|
141
|
-
foxes/input/yaml/windio/read_outputs.py,sha256=
|
|
142
|
-
foxes/input/yaml/windio/read_site.py,sha256=
|
|
143
|
-
foxes/input/yaml/windio/windio.py,sha256=
|
|
138
|
+
foxes/input/yaml/windio/read_attributes.py,sha256=T4FLMGVgWWK4cyNnq0H8x7TX_pbeUv-X4NEmCC-0IBs,13252
|
|
139
|
+
foxes/input/yaml/windio/read_farm.py,sha256=TraS7AYIbu8BVj9ml8dj9yWN9dCZ_VoHrrFkmWWaU28,8247
|
|
140
|
+
foxes/input/yaml/windio/read_fields.py,sha256=pgMMkXaZ8BXzTIyNqgFxJCR_QvO7rn5xEEP77NjD17k,4818
|
|
141
|
+
foxes/input/yaml/windio/read_outputs.py,sha256=IbD5_0PLMy6Dl1-oyCDoY4S6fetD7j03iUZG2cIJ7yY,8678
|
|
142
|
+
foxes/input/yaml/windio/read_site.py,sha256=csmhoe46b3nUecMR9Nuc5vifAvOHB2g3SyR8MvFHzp8,13840
|
|
143
|
+
foxes/input/yaml/windio/windio.py,sha256=mcznjZCwUpX06ADMvhp-kQMeBZG4pP7ooILb6-UH5_A,5659
|
|
144
144
|
foxes/models/__init__.py,sha256=-wXjx9PkxWT2Koq4tmtCuasnlb8RIeLVWP7iSYPQ1Fc,727
|
|
145
145
|
foxes/models/model_book.py,sha256=A9lCg-cQtGVQ2dpIGzcEJGHdyktUdpzqyqHrybUMRvo,30065
|
|
146
146
|
foxes/models/axial_induction/__init__.py,sha256=QJN1RLxIt1EhQXIDVLjPSZ1zIoaS6YjK9VDdgw7NwsA,124
|
|
147
147
|
foxes/models/axial_induction/betz.py,sha256=rAaq7pnu-FmfYh61BU5Af1h4_bG2AAimP4Qah1aZo88,894
|
|
148
148
|
foxes/models/axial_induction/madsen.py,sha256=_-ycfh8SnIpCKWm1uwx5VH7f49FQvR0y1Nbb_U8xWyU,1403
|
|
149
|
-
foxes/models/farm_controllers/__init__.py,sha256=
|
|
149
|
+
foxes/models/farm_controllers/__init__.py,sha256=9c9vvgfUAvOG1I_5Bp58zJPC1mvUFuSQCDbRAUFTj4c,153
|
|
150
150
|
foxes/models/farm_controllers/basic.py,sha256=6pinNXiyfoG3apXhqQWcnxx4vN_7Q63YryXX5Z7kTE0,249
|
|
151
|
+
foxes/models/farm_controllers/op_flag.py,sha256=EEtPejZ5majpDiPO_8Y5Z6b2deNpj1PyOX7wsl56Shk,6021
|
|
151
152
|
foxes/models/farm_models/__init__.py,sha256=8qV0dQ2N3HJpbOolhLtBs0LMdC8hctxy8J-OiqcSvKo,87
|
|
152
153
|
foxes/models/farm_models/turbine2farm.py,sha256=LuK-qAy4aVXBqFCM4-1qogwAA4qfHsjYRFsrZy_OUro,2276
|
|
153
154
|
foxes/models/ground_models/__init__.py,sha256=r_MuSulOGQ1SnrojfpwU9kky7tZhPtCwXbXIVvGdrkg,148
|
|
@@ -220,17 +221,17 @@ foxes/models/wake_models/top_hat.py,sha256=APZf6r26jfi2rP_rrmk4qXs1NGlzc1hsFxrj6
|
|
|
220
221
|
foxes/models/wake_models/induction/__init__.py,sha256=xw5LiTh2YWRRNF8cyYACQc-735C23NarCMHWiHQ_5-8,311
|
|
221
222
|
foxes/models/wake_models/induction/rankine_half_body.py,sha256=1NaV5eqcsxjlQwCSUDC-w3wO_SGgh4ykEYvNJX8ToBk,6427
|
|
222
223
|
foxes/models/wake_models/induction/rathmann.py,sha256=ZPF16PESm1wWA7SL7sNbj_XPb4rAGGcmfBrby8VoU3o,7964
|
|
223
|
-
foxes/models/wake_models/induction/self_similar.py,sha256=
|
|
224
|
-
foxes/models/wake_models/induction/self_similar2020.py,sha256=
|
|
224
|
+
foxes/models/wake_models/induction/self_similar.py,sha256=WO5NStvfAy2xT-i4zW63ncyn-NH4_fNPAzv--nQjJvA,8869
|
|
225
|
+
foxes/models/wake_models/induction/self_similar2020.py,sha256=FETB7iiS1av0ymb8w3sgYLRCK3jz0lVXAMgGZ6MXljg,1516
|
|
225
226
|
foxes/models/wake_models/induction/vortex_sheet.py,sha256=Iy3QX_2lUA7MiEEYKFeRh7jz9s7KpyyS7qBLhfCEsAo,7197
|
|
226
227
|
foxes/models/wake_models/ti/__init__.py,sha256=0ZKF4sHbtU3QCRzC1Ff0vnVymbdby7s12Qcy3PnBgKU,163
|
|
227
|
-
foxes/models/wake_models/ti/crespo_hernandez.py,sha256=
|
|
228
|
+
foxes/models/wake_models/ti/crespo_hernandez.py,sha256=Or1uf0t8GjtQePyiczSIf4Dmb8tl4AMqdV9TqWFQNbE,9005
|
|
228
229
|
foxes/models/wake_models/ti/iec_ti.py,sha256=P9SUNaxf9UdA_rufuJcmpgLXM1Fj1FRhFHU4DNxYFa4,7064
|
|
229
230
|
foxes/models/wake_models/wind/__init__.py,sha256=QOCeb8E7TYuwkX5jhgPUST1kGmv9c59qvclLhtUeLnQ,379
|
|
230
|
-
foxes/models/wake_models/wind/bastankhah14.py,sha256=
|
|
231
|
-
foxes/models/wake_models/wind/bastankhah16.py,sha256=
|
|
231
|
+
foxes/models/wake_models/wind/bastankhah14.py,sha256=0NxM4QO1CtaY7dim2Xc7CXK3uMMWCMkhuOd3Wnb75RU,5582
|
|
232
|
+
foxes/models/wake_models/wind/bastankhah16.py,sha256=FuBQi9Q01f6gIK0_S5aO6QpCPJvyFzqH8wV44q1eTIw,18743
|
|
232
233
|
foxes/models/wake_models/wind/jensen.py,sha256=rGEtBgTtT1z3_sGVHkAlqSP4sSErD2yQu-lDwqfykIw,4493
|
|
233
|
-
foxes/models/wake_models/wind/turbopark.py,sha256=
|
|
234
|
+
foxes/models/wake_models/wind/turbopark.py,sha256=w0ZXloSgjsbk32JuivrmVF4WbVv0TNE3KiU9UC07Y4c,15237
|
|
234
235
|
foxes/models/wake_superpositions/__init__.py,sha256=fMrBOoBGSa45xbc2E1Jdgjfkm2ahKBKgPeBVq8s9uH0,690
|
|
235
236
|
foxes/models/wake_superpositions/ti_linear.py,sha256=Cqteww87M94ZDIrSoAoXSouCcH-Auj0u8NSD6JCv9Lw,3895
|
|
236
237
|
foxes/models/wake_superpositions/ti_max.py,sha256=s2NYnqMIk-Bj6-SAUyhBX0WWEye5yu4hRoe5dGcLEAw,3920
|
|
@@ -255,7 +256,7 @@ foxes/output/rose_plot.py,sha256=bHd9LrGCsE39zUxmiaRk8Z3r2m3csWqSUTS-3H-vdnk,188
|
|
|
255
256
|
foxes/output/rotor_point_plots.py,sha256=J2gfwDZVBrQIgCk6RJuj0Jq1UA1cmyh7k8VC2TfV6xw,3324
|
|
256
257
|
foxes/output/slice_data.py,sha256=bnY8D0ITFFN-i1mSkm0e2ukIMqxjev2KaUINbxo62pA,33788
|
|
257
258
|
foxes/output/slices_data.py,sha256=FqulnXnZ5aI2fOns4ffBYSw5j42IEGq-lLCNJxWG5HA,8671
|
|
258
|
-
foxes/output/state_turbine_map.py,sha256=
|
|
259
|
+
foxes/output/state_turbine_map.py,sha256=tBHDbAqxEqanVYRJhPlpvIV6FslZGG0VYEfRzEfh5AI,2944
|
|
259
260
|
foxes/output/state_turbine_table.py,sha256=ldG0LcC126YsXQZtJY9OSWxW3ETbHdBehjtU21caTDw,2228
|
|
260
261
|
foxes/output/turbine_type_curves.py,sha256=fvODho-HmH8hIrv0iQ6BXqtQ4Hz0jomnOTK-kV7vfBQ,5724
|
|
261
262
|
foxes/output/flow_plots_2d/__init__.py,sha256=5pFJqvSuZKkm1TkN3d7won0mPLvr9MUg9m0TMlOqbec,91
|
|
@@ -295,7 +296,7 @@ foxes/utils/geom2d/example_intersection.py,sha256=4e6sjpZEk_bNc462YvwKPzwxdV1B90
|
|
|
295
296
|
foxes/utils/geom2d/example_union.py,sha256=BKfLt1mtQcSto-qExeMQkq8tQ6kfFXVJ93Cc7DhOal8,1750
|
|
296
297
|
foxes/utils/geom2d/half_plane.py,sha256=kzZD6pkZxZ03MK9WAboWzXb5Ws5dWLQY9GIahD4D9mA,6167
|
|
297
298
|
foxes/utils/geom2d/polygon.py,sha256=Xj7triA5Pe4-48sNSAvGxEXlQGptV161LUpKKCf3YOY,5535
|
|
298
|
-
foxes-1.5.
|
|
299
|
+
foxes-1.5.2.dist-info/licenses/LICENSE,sha256=bBCH6mYTPzSepk2s2UUZ3II_ZYXrn1bnSqB85-aZHxU,1071
|
|
299
300
|
tests/0_consistency/iterative/test_iterative.py,sha256=lzagmJ1y241l6Szw4Cu80S8S1ATHIyD7ukr1vVBrusY,2637
|
|
300
301
|
tests/0_consistency/partial_wakes/test_partial_wakes.py,sha256=7rdg2lcUYUzxwCdGhue7A4QYCJQGrOO4E0bytgatYj4,2584
|
|
301
302
|
tests/1_verification/flappy_0_6/PCt_files/test_PCt_files.py,sha256=8tIqifsykvxMCd9eD-mZWxRwT56sKjIxrGf3hf8aCFA,2530
|
|
@@ -320,9 +321,10 @@ tests/1_verification/flappy_0_6_2/row_Bastankhah_Crespo/test_row_Bastankhah_Cres
|
|
|
320
321
|
tests/1_verification/flappy_0_6_2/row_Bastankhah_Crespo/flappy/run.py,sha256=nwIyn20ZyYHhCKcPCnm02zjwNKMRzr9t0U8TjKK61QU,2213
|
|
321
322
|
tests/1_verification/flappy_0_6_2/row_Bastankhah_linear_centre/test_row_Bastankhah_linear_centre.py,sha256=QUULW3AJJq8zvUIdIQHkXiNZpaysVYIALh5HOJ6-428,2595
|
|
322
323
|
tests/1_verification/flappy_0_6_2/row_Bastankhah_linear_centre/flappy/run.py,sha256=1paRjCe71AIM8igK4_f0FFH1xiIETvuBwnZAATiwWUU,2102
|
|
324
|
+
tests/2_models/turbine_models/test_set_farm_vars.py,sha256=_y-lVYsL9jByh_34c08Qu4GgYxW8s-E2HsSyX7ptfnY,1680
|
|
323
325
|
tests/3_examples/test_examples.py,sha256=9_PtvlYA6ELsQGHt-xAnsjCYdGj1ekX237ymWvEJaCk,732
|
|
324
|
-
foxes-1.5.
|
|
325
|
-
foxes-1.5.
|
|
326
|
-
foxes-1.5.
|
|
327
|
-
foxes-1.5.
|
|
328
|
-
foxes-1.5.
|
|
326
|
+
foxes-1.5.2.dist-info/METADATA,sha256=yJDpMwsBVrfk6vpMRDi85OFO89RTham8VVQk1-Bre7Y,8095
|
|
327
|
+
foxes-1.5.2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
328
|
+
foxes-1.5.2.dist-info/entry_points.txt,sha256=KuS44FRH5NnMw201A8Btr76eNRKr2UOoKHjejAsqKwE,123
|
|
329
|
+
foxes-1.5.2.dist-info/top_level.txt,sha256=G7oHApEz5nc-iP__XsPcvjYe_NyXGmKMUMPHi3C3x6I,26
|
|
330
|
+
foxes-1.5.2.dist-info/RECORD,,
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
|
|
3
|
+
import foxes
|
|
4
|
+
import foxes.variables as FV
|
|
5
|
+
import foxes.constants as FC
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def test_set_farm_vars():
|
|
9
|
+
n_s = 360
|
|
10
|
+
n_tr = 3
|
|
11
|
+
|
|
12
|
+
wd = np.arange(0.0, 360.0, 360 / n_s)
|
|
13
|
+
states = foxes.input.states.ScanStates(
|
|
14
|
+
scans={
|
|
15
|
+
FV.WD: wd,
|
|
16
|
+
FV.WS: [9.0],
|
|
17
|
+
FV.TI: [0.04],
|
|
18
|
+
FV.RHO: [1.225],
|
|
19
|
+
},
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
n_t = n_tr**2
|
|
23
|
+
x = np.zeros((n_s, n_t), dtype=foxes.config.dtype_double)
|
|
24
|
+
x[:] = wd[:, None] + np.arange(n_t)[None, :] / 10
|
|
25
|
+
|
|
26
|
+
farm = foxes.WindFarm()
|
|
27
|
+
foxes.input.farm_layout.add_grid(
|
|
28
|
+
farm,
|
|
29
|
+
xy_base=[0.0, 0.0],
|
|
30
|
+
step_vectors=[[800.0, 0.0], [0.0, 800.0]],
|
|
31
|
+
steps=[n_tr, n_tr],
|
|
32
|
+
turbine_models=["NREL5MW", "set_x"],
|
|
33
|
+
verbosity=0,
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
with foxes.Engine.new("default", verbosity=0):
|
|
37
|
+
for pr in [False, True]:
|
|
38
|
+
print(f"\npre_rotor = {pr}\n")
|
|
39
|
+
|
|
40
|
+
mbook = foxes.ModelBook()
|
|
41
|
+
mbook.turbine_models["set_x"] = foxes.models.turbine_models.SetFarmVars(
|
|
42
|
+
pre_rotor=pr
|
|
43
|
+
)
|
|
44
|
+
mbook.turbine_models["set_x"].add_var("x", x)
|
|
45
|
+
|
|
46
|
+
algo = foxes.algorithms.Downwind(
|
|
47
|
+
farm=farm,
|
|
48
|
+
states=states,
|
|
49
|
+
wake_models=["Bastankhah2014_linear_lim_k004"],
|
|
50
|
+
mbook=mbook,
|
|
51
|
+
verbosity=0,
|
|
52
|
+
)
|
|
53
|
+
|
|
54
|
+
farm_results = algo.calc_farm()
|
|
55
|
+
|
|
56
|
+
fr = farm_results.to_dataframe()
|
|
57
|
+
print(fr[[FV.WD, "x"]])
|
|
58
|
+
|
|
59
|
+
for i, g in fr.reset_index().groupby(FC.TURBINE):
|
|
60
|
+
assert np.allclose(g["x"].values, g[FV.WD].values + i / 10)
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
if __name__ == "__main__":
|
|
64
|
+
test_set_farm_vars()
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|