foxes 1.0__py3-none-any.whl → 1.1.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of foxes might be problematic. Click here for more details.
- docs/source/conf.py +0 -1
- examples/states_lookup_table/run.py +1 -1
- examples/timeseries/run.py +11 -4
- foxes/algorithms/downwind/downwind.py +18 -13
- foxes/algorithms/downwind/models/farm_wakes_calc.py +1 -1
- foxes/algorithms/downwind/models/init_farm_data.py +1 -1
- foxes/algorithms/downwind/models/point_wakes_calc.py +1 -1
- foxes/algorithms/downwind/models/reorder_farm_output.py +1 -1
- foxes/algorithms/downwind/models/set_amb_farm_results.py +1 -1
- foxes/algorithms/downwind/models/set_amb_point_results.py +1 -1
- foxes/algorithms/iterative/iterative.py +1 -1
- foxes/algorithms/iterative/models/farm_wakes_calc.py +1 -1
- foxes/algorithms/iterative/models/urelax.py +3 -3
- foxes/algorithms/sequential/models/plugin.py +4 -4
- foxes/algorithms/sequential/models/seq_state.py +1 -1
- foxes/constants.py +5 -5
- foxes/core/algorithm.py +2 -2
- foxes/core/data_calc_model.py +2 -2
- foxes/core/engine.py +20 -10
- foxes/core/farm_controller.py +3 -3
- foxes/core/farm_data_model.py +1 -1
- foxes/core/ground_model.py +2 -2
- foxes/core/model.py +122 -108
- foxes/core/partial_wakes_model.py +1 -1
- foxes/core/point_data_model.py +2 -2
- foxes/core/states.py +1 -1
- foxes/core/turbine_type.py +2 -2
- foxes/core/wake_frame.py +8 -30
- foxes/core/wake_model.py +3 -2
- foxes/core/wake_superposition.py +1 -1
- foxes/data/windio/windio_5turbines_timeseries.yaml +9 -15
- foxes/engines/__init__.py +1 -0
- foxes/engines/dask.py +13 -6
- foxes/engines/multiprocess.py +5 -8
- foxes/engines/numpy.py +8 -26
- foxes/engines/pool.py +10 -24
- foxes/engines/ray.py +79 -0
- foxes/engines/single.py +3 -1
- foxes/input/farm_layout/from_json.py +1 -1
- foxes/input/states/__init__.py +1 -0
- foxes/input/states/field_data_nc.py +4 -4
- foxes/input/states/multi_height.py +4 -4
- foxes/input/states/scan_ws.py +1 -1
- foxes/input/states/single.py +1 -1
- foxes/input/states/slice_data_nc.py +681 -0
- foxes/input/states/states_table.py +3 -3
- foxes/input/windio/__init__.py +1 -1
- foxes/input/windio/read_attributes.py +8 -2
- foxes/input/windio/read_fields.py +3 -0
- foxes/input/windio/read_outputs.py +8 -2
- foxes/input/windio/windio.py +6 -2
- foxes/models/farm_models/turbine2farm.py +1 -1
- foxes/models/ground_models/wake_mirror.py +2 -2
- foxes/models/model_book.py +29 -2
- foxes/models/partial_wakes/axiwake.py +3 -3
- foxes/models/partial_wakes/top_hat.py +2 -2
- foxes/models/point_models/set_uniform_data.py +1 -1
- foxes/models/point_models/tke2ti.py +1 -1
- foxes/models/point_models/wake_deltas.py +1 -1
- foxes/models/rotor_models/grid.py +2 -2
- foxes/models/turbine_models/calculator.py +4 -4
- foxes/models/turbine_models/kTI_model.py +22 -6
- foxes/models/turbine_models/lookup_table.py +3 -2
- foxes/models/turbine_types/PCt_file.py +5 -5
- foxes/models/turbine_types/PCt_from_two.py +5 -5
- foxes/models/turbine_types/TBL_file.py +80 -0
- foxes/models/turbine_types/__init__.py +1 -0
- foxes/models/turbine_types/lookup.py +5 -5
- foxes/models/turbine_types/null_type.py +3 -3
- foxes/models/turbine_types/wsrho2PCt_from_two.py +7 -7
- foxes/models/turbine_types/wsti2PCt_from_two.py +9 -9
- foxes/models/vertical_profiles/__init__.py +1 -1
- foxes/models/wake_frames/dynamic_wakes.py +2 -2
- foxes/models/wake_frames/farm_order.py +2 -2
- foxes/models/wake_frames/rotor_wd.py +2 -2
- foxes/models/wake_frames/seq_dynamic_wakes.py +5 -11
- foxes/models/wake_frames/streamlines.py +2 -2
- foxes/models/wake_frames/timelines.py +2 -2
- foxes/models/wake_frames/yawed_wakes.py +3 -3
- foxes/models/wake_models/dist_sliced.py +1 -1
- foxes/models/wake_models/induction/rankine_half_body.py +1 -1
- foxes/models/wake_models/induction/rathmann.py +76 -22
- foxes/models/wake_models/induction/self_similar.py +76 -26
- foxes/models/wake_models/induction/vortex_sheet.py +84 -46
- foxes/models/wake_models/ti/crespo_hernandez.py +6 -4
- foxes/models/wake_models/ti/iec_ti.py +7 -5
- foxes/models/wake_models/wind/bastankhah14.py +6 -4
- foxes/models/wake_models/wind/bastankhah16.py +9 -9
- foxes/models/wake_models/wind/jensen.py +3 -2
- foxes/models/wake_models/wind/turbopark.py +14 -11
- foxes/models/wake_superpositions/ti_linear.py +1 -1
- foxes/models/wake_superpositions/ti_max.py +1 -1
- foxes/models/wake_superpositions/ti_pow.py +1 -1
- foxes/models/wake_superpositions/ti_quadratic.py +1 -1
- foxes/models/wake_superpositions/ws_linear.py +8 -7
- foxes/models/wake_superpositions/ws_max.py +8 -7
- foxes/models/wake_superpositions/ws_pow.py +8 -7
- foxes/models/wake_superpositions/ws_product.py +5 -5
- foxes/models/wake_superpositions/ws_quadratic.py +8 -7
- foxes/output/farm_layout.py +14 -10
- foxes/output/farm_results_eval.py +1 -1
- foxes/output/grids.py +1 -1
- foxes/output/results_writer.py +2 -2
- foxes/output/rose_plot.py +3 -3
- foxes/output/seq_plugins/seq_flow_ani_plugin.py +2 -2
- foxes/output/seq_plugins/seq_wake_debug_plugin.py +2 -2
- foxes/output/state_turbine_map.py +1 -1
- foxes/utils/abl/neutral.py +2 -2
- foxes/utils/abl/stable.py +2 -2
- foxes/utils/abl/unstable.py +2 -2
- foxes/utils/data_book.py +1 -1
- foxes/utils/dict.py +23 -0
- foxes/utils/exec_python.py +1 -1
- foxes/utils/factory.py +29 -1
- foxes/utils/geom2d/circle.py +1 -1
- foxes/utils/geom2d/polygon.py +1 -1
- foxes/utils/geopandas_utils.py +2 -2
- foxes/utils/load.py +2 -2
- foxes/utils/pandas_helpers.py +1 -1
- foxes/utils/xarray_utils.py +1 -1
- foxes/variables.py +3 -3
- {foxes-1.0.dist-info → foxes-1.1.1.dist-info}/METADATA +8 -6
- {foxes-1.0.dist-info → foxes-1.1.1.dist-info}/RECORD +127 -125
- {foxes-1.0.dist-info → foxes-1.1.1.dist-info}/WHEEL +1 -1
- foxes/utils/geopandas_helpers.py +0 -294
- /examples/{induction_RHB → induction}/run.py +0 -0
- {foxes-1.0.dist-info → foxes-1.1.1.dist-info}/LICENSE +0 -0
- {foxes-1.0.dist-info → foxes-1.1.1.dist-info}/top_level.txt +0 -0
|
@@ -24,6 +24,7 @@ def _read_wind_deficit(
|
|
|
24
24
|
{
|
|
25
25
|
"Linear": "ws_linear",
|
|
26
26
|
"Quadratic": "ws_quadratic",
|
|
27
|
+
"Product": "ws_product",
|
|
27
28
|
},
|
|
28
29
|
name="ws_sup_dict",
|
|
29
30
|
)
|
|
@@ -31,6 +32,7 @@ def _read_wind_deficit(
|
|
|
31
32
|
{
|
|
32
33
|
"Linear": "ws_linear_amb",
|
|
33
34
|
"Quadratic": "ws_quadratic_amb",
|
|
35
|
+
"Product": "ws_product",
|
|
34
36
|
},
|
|
35
37
|
name="ws_sup_dict",
|
|
36
38
|
)
|
|
@@ -311,7 +313,7 @@ def _read_analysis(wio_ana, algo_dict, verbosity):
|
|
|
311
313
|
print("deflection_model not found, using default settings")
|
|
312
314
|
|
|
313
315
|
|
|
314
|
-
def read_attributes(wio, algo_dict, verbosity):
|
|
316
|
+
def read_attributes(wio, algo_dict, verbosity=1, **output_pars):
|
|
315
317
|
"""
|
|
316
318
|
Reads the attributes part of windio
|
|
317
319
|
|
|
@@ -323,6 +325,8 @@ def read_attributes(wio, algo_dict, verbosity):
|
|
|
323
325
|
The algorithm dictionary
|
|
324
326
|
verbosity: int
|
|
325
327
|
The verbosity level, 0=silent
|
|
328
|
+
**output_pars: dict, optional
|
|
329
|
+
Additional parameters for output reading
|
|
326
330
|
|
|
327
331
|
Returns
|
|
328
332
|
-------
|
|
@@ -358,6 +362,8 @@ def read_attributes(wio, algo_dict, verbosity):
|
|
|
358
362
|
out_dicts = []
|
|
359
363
|
if "outputs" in wio_attrs:
|
|
360
364
|
outputs = Dict(wio_attrs["outputs"], name="outputs")
|
|
361
|
-
out_dicts, odir = read_outputs(
|
|
365
|
+
out_dicts, odir = read_outputs(
|
|
366
|
+
outputs, algo_dict, verbosity=verbosity, **output_pars
|
|
367
|
+
)
|
|
362
368
|
|
|
363
369
|
return out_dicts, odir
|
|
@@ -126,7 +126,7 @@ def _read_flow_field(wio_outs, odir, out_dicts, verbosity):
|
|
|
126
126
|
)
|
|
127
127
|
|
|
128
128
|
|
|
129
|
-
def read_outputs(wio_outs, algo_dict, verbosity):
|
|
129
|
+
def read_outputs(wio_outs, algo_dict, output_dir=None, verbosity=1):
|
|
130
130
|
"""
|
|
131
131
|
Reads the windio outputs
|
|
132
132
|
|
|
@@ -136,6 +136,8 @@ def read_outputs(wio_outs, algo_dict, verbosity):
|
|
|
136
136
|
The windio output data
|
|
137
137
|
algo_dict: dict
|
|
138
138
|
The algorithm dictionary
|
|
139
|
+
output_dir: pathlib.Path, optional
|
|
140
|
+
Path to the output folder
|
|
139
141
|
verbosity: int
|
|
140
142
|
The verbosity level, 0=silent
|
|
141
143
|
|
|
@@ -150,7 +152,11 @@ def read_outputs(wio_outs, algo_dict, verbosity):
|
|
|
150
152
|
|
|
151
153
|
"""
|
|
152
154
|
out_dicts = []
|
|
153
|
-
odir =
|
|
155
|
+
odir = (
|
|
156
|
+
Path(output_dir)
|
|
157
|
+
if output_dir is not None
|
|
158
|
+
else Path(wio_outs.pop("output_folder", "results"))
|
|
159
|
+
)
|
|
154
160
|
odir.mkdir(exist_ok=True, parents=True)
|
|
155
161
|
if verbosity > 2:
|
|
156
162
|
print(" Reading outputs")
|
foxes/input/windio/windio.py
CHANGED
|
@@ -95,6 +95,7 @@ def read_windio(
|
|
|
95
95
|
windio_yaml,
|
|
96
96
|
verbosity=1,
|
|
97
97
|
algo_pars=None,
|
|
98
|
+
output_dir=None,
|
|
98
99
|
**runner_pars,
|
|
99
100
|
):
|
|
100
101
|
"""
|
|
@@ -111,6 +112,8 @@ def read_windio(
|
|
|
111
112
|
The verbosity level, 0 = silent
|
|
112
113
|
algo_pars: dict, optional
|
|
113
114
|
Additional algorithm parameters
|
|
115
|
+
output_dir: str, optional
|
|
116
|
+
Path to the output folder
|
|
114
117
|
runner_pars: dict, optional
|
|
115
118
|
Additional parameters for the WindioRunner
|
|
116
119
|
|
|
@@ -130,7 +133,7 @@ def read_windio(
|
|
|
130
133
|
if verbosity > 0:
|
|
131
134
|
print(f"Reading windio file {wio_file}")
|
|
132
135
|
|
|
133
|
-
yml_utils = import_module("windIO.utils.yml_utils", hint="pip install
|
|
136
|
+
yml_utils = import_module("windIO.utils.yml_utils", hint="pip install git+https://github.com/kilojoules/windIO@master#egg=windIO")
|
|
134
137
|
wio = yml_utils.load_yaml(wio_file)
|
|
135
138
|
|
|
136
139
|
if verbosity > 1:
|
|
@@ -155,7 +158,8 @@ def read_windio(
|
|
|
155
158
|
out_dicts, odir = read_attributes(
|
|
156
159
|
wio,
|
|
157
160
|
algo_dict,
|
|
158
|
-
|
|
161
|
+
output_dir=output_dir,
|
|
162
|
+
verbosity=verbosity,
|
|
159
163
|
)
|
|
160
164
|
|
|
161
165
|
if verbosity > 1:
|
|
@@ -56,7 +56,7 @@ class WakeMirror(GroundModel):
|
|
|
56
56
|
The target point data
|
|
57
57
|
downwind_index: int
|
|
58
58
|
The index of the wake causing turbine
|
|
59
|
-
in the
|
|
59
|
+
in the downwind order
|
|
60
60
|
wake_deltas: dict
|
|
61
61
|
The wake deltas. Key: variable name,
|
|
62
62
|
value: numpy.ndarray with shape
|
|
@@ -117,7 +117,7 @@ class WakeMirror(GroundModel):
|
|
|
117
117
|
The target point data
|
|
118
118
|
downwind_index: int
|
|
119
119
|
The index of the wake causing turbine
|
|
120
|
-
in the
|
|
120
|
+
in the downwind order
|
|
121
121
|
wake_deltas: dict
|
|
122
122
|
The wake deltas. Key: variable name,
|
|
123
123
|
value: numpy.ndarray with shape
|
foxes/models/model_book.py
CHANGED
|
@@ -460,12 +460,39 @@ class ModelBook:
|
|
|
460
460
|
)
|
|
461
461
|
|
|
462
462
|
self.wake_models[f"RHB"] = fm.wake_models.induction.RankineHalfBody()
|
|
463
|
+
|
|
464
|
+
self.wake_models[f"VortexSheet"] = fm.wake_models.induction.VortexSheet()
|
|
465
|
+
self.wake_models.add_factory(
|
|
466
|
+
fm.wake_models.induction.VortexSheet,
|
|
467
|
+
"VortexSheet_<superposition>",
|
|
468
|
+
superposition=lambda s: f"ws_{s}",
|
|
469
|
+
hints={"superposition": "(Superposition, e.g. linear for ws_linear)"},
|
|
470
|
+
)
|
|
471
|
+
|
|
463
472
|
self.wake_models[f"Rathmann"] = fm.wake_models.induction.Rathmann()
|
|
473
|
+
self.wake_models.add_factory(
|
|
474
|
+
fm.wake_models.induction.Rathmann,
|
|
475
|
+
"Rathmann_<superposition>",
|
|
476
|
+
superposition=lambda s: f"ws_{s}",
|
|
477
|
+
hints={"superposition": "(Superposition, e.g. linear for ws_linear)"},
|
|
478
|
+
)
|
|
479
|
+
|
|
464
480
|
self.wake_models[f"SelfSimilar"] = fm.wake_models.induction.SelfSimilar()
|
|
465
481
|
self.wake_models[f"SelfSimilar2020"] = (
|
|
466
482
|
fm.wake_models.induction.SelfSimilar2020()
|
|
467
483
|
)
|
|
468
|
-
self.wake_models
|
|
484
|
+
self.wake_models.add_factory(
|
|
485
|
+
fm.wake_models.induction.SelfSimilar,
|
|
486
|
+
"SelfSimilar_<superposition>",
|
|
487
|
+
superposition=lambda s: f"ws_{s}",
|
|
488
|
+
hints={"superposition": "(Superposition, e.g. linear for ws_linear)"},
|
|
489
|
+
)
|
|
490
|
+
self.wake_models.add_factory(
|
|
491
|
+
fm.wake_models.induction.SelfSimilar2020,
|
|
492
|
+
"SelfSimilar2020_<superposition>",
|
|
493
|
+
superposition=lambda s: f"ws_{s}",
|
|
494
|
+
hints={"superposition": "(Superposition, e.g. linear for ws_linear)"},
|
|
495
|
+
)
|
|
469
496
|
|
|
470
497
|
self.ground_models = FDict(name="ground_models")
|
|
471
498
|
self.ground_models["no_ground"] = fm.ground_models.NoGround()
|
|
@@ -515,7 +542,7 @@ class ModelBook:
|
|
|
515
542
|
m.name = k
|
|
516
543
|
|
|
517
544
|
def __getitem__(self, key):
|
|
518
|
-
return self.sources.
|
|
545
|
+
return self.sources.get_item(key)
|
|
519
546
|
|
|
520
547
|
def print_toc(self, subset=None, search=None):
|
|
521
548
|
"""
|
|
@@ -95,7 +95,7 @@ class PartialAxiwake(PartialCentre):
|
|
|
95
95
|
The target point data
|
|
96
96
|
downwind_index: int
|
|
97
97
|
The index of the wake causing turbine
|
|
98
|
-
in the
|
|
98
|
+
in the downwind order
|
|
99
99
|
wake_deltas: dict
|
|
100
100
|
The wake deltas. Key: variable name,
|
|
101
101
|
value: numpy.ndarray with shape
|
|
@@ -127,7 +127,7 @@ class PartialAxiwake(PartialCentre):
|
|
|
127
127
|
wcoos = algo.wake_frame.get_wake_coos(algo, mdata, fdata, tdata, downwind_index)
|
|
128
128
|
|
|
129
129
|
# prepare x and r coordinates:
|
|
130
|
-
x =
|
|
130
|
+
x = wcoos[..., 0, 0]
|
|
131
131
|
n = wcoos[..., 0, 1:3]
|
|
132
132
|
R = np.linalg.norm(n, axis=-1)
|
|
133
133
|
r = np.zeros((n_states, n_targets, self.n), dtype=FC.DTYPE)
|
|
@@ -145,7 +145,7 @@ class PartialAxiwake(PartialCentre):
|
|
|
145
145
|
n[:, :, 0][~sel] = 1
|
|
146
146
|
|
|
147
147
|
# case wake centre outside rotor disk:
|
|
148
|
-
sel = (x >
|
|
148
|
+
sel = (x > 1e-8) & (R > D / 2)
|
|
149
149
|
if np.any(sel):
|
|
150
150
|
n_sel = np.sum(sel)
|
|
151
151
|
Rsel = np.zeros((n_sel, self.n + 1), dtype=FC.DTYPE)
|
|
@@ -121,7 +121,7 @@ class PartialTopHat(PartialCentre):
|
|
|
121
121
|
The target point data
|
|
122
122
|
downwind_index: int
|
|
123
123
|
The index of the wake causing turbine
|
|
124
|
-
in the
|
|
124
|
+
in the downwind order
|
|
125
125
|
wake_deltas: dict
|
|
126
126
|
The wake deltas. Key: variable name,
|
|
127
127
|
value: numpy.ndarray with shape
|
|
@@ -148,7 +148,7 @@ class PartialTopHat(PartialCentre):
|
|
|
148
148
|
upcast=True,
|
|
149
149
|
)
|
|
150
150
|
|
|
151
|
-
sel0 = (ct >
|
|
151
|
+
sel0 = (ct > 1e-8) & (x > 1e-8)
|
|
152
152
|
if np.any(sel0):
|
|
153
153
|
R = np.linalg.norm(yz, axis=-1)
|
|
154
154
|
del yz
|
|
@@ -16,7 +16,7 @@ class GridRotor(RotorModel):
|
|
|
16
16
|
maximal number of points is N = n * n
|
|
17
17
|
reduce: bool
|
|
18
18
|
Flag for reduction to points actually representing
|
|
19
|
-
an area with overlap with the
|
|
19
|
+
an area with overlap with the circle, recalculating
|
|
20
20
|
the self.__weights accordingly
|
|
21
21
|
nint: int
|
|
22
22
|
Integration steps per element
|
|
@@ -36,7 +36,7 @@ class GridRotor(RotorModel):
|
|
|
36
36
|
maximal number of points is N = n * n
|
|
37
37
|
reduce: bool
|
|
38
38
|
Flag for reduction to points actually representing
|
|
39
|
-
an area with overlap with the
|
|
39
|
+
an area with overlap with the circle, recalculating
|
|
40
40
|
the self.__weights accordingly
|
|
41
41
|
nint: int
|
|
42
42
|
Integration steps per element
|
|
@@ -8,11 +8,11 @@ class Calculator(TurbineModel):
|
|
|
8
8
|
Attributes
|
|
9
9
|
----------
|
|
10
10
|
in_vars: list of str
|
|
11
|
-
The input farm
|
|
11
|
+
The input farm variables
|
|
12
12
|
out_vars: list of str
|
|
13
13
|
The output variables
|
|
14
14
|
func: Function
|
|
15
|
-
The function: f(in0, in1, ..., stsel) -> (out0,
|
|
15
|
+
The function: f(in0, in1, ..., stsel) -> (out0, out1, ...)
|
|
16
16
|
where inX and outY are numpy.ndarrays and
|
|
17
17
|
st_sel is the state-turbine selection slice or array.
|
|
18
18
|
All arrays have shape (n_states, n_turbines).
|
|
@@ -28,11 +28,11 @@ class Calculator(TurbineModel):
|
|
|
28
28
|
Parameters
|
|
29
29
|
----------
|
|
30
30
|
in_vars: list of str
|
|
31
|
-
The input farm
|
|
31
|
+
The input farm variables
|
|
32
32
|
out_vars: list of str
|
|
33
33
|
The output variables
|
|
34
34
|
func: Function
|
|
35
|
-
The function: f(in0, in1, ..., stsel) -> (out0,
|
|
35
|
+
The function: f(in0, in1, ..., stsel) -> (out0, out1, ...)
|
|
36
36
|
where inX and outY are numpy.ndarrays and
|
|
37
37
|
st_sel is the state-turbine selection slice or array.
|
|
38
38
|
All arrays have shape (n_states, n_turbines).
|
|
@@ -101,15 +101,31 @@ class kTI(TurbineModel):
|
|
|
101
101
|
Values: numpy.ndarray with shape (n_states, n_turbines)
|
|
102
102
|
|
|
103
103
|
"""
|
|
104
|
+
|
|
104
105
|
kti = self.get_data(
|
|
105
|
-
FV.KTI,
|
|
106
|
-
|
|
106
|
+
FV.KTI,
|
|
107
|
+
FC.STATE_TURBINE,
|
|
108
|
+
lookup="sf",
|
|
109
|
+
fdata=fdata,
|
|
110
|
+
upcast=False,
|
|
111
|
+
selection=st_sel,
|
|
112
|
+
)
|
|
107
113
|
kb = self.get_data(
|
|
108
|
-
FV.KB,
|
|
109
|
-
|
|
114
|
+
FV.KB,
|
|
115
|
+
FC.STATE_TURBINE,
|
|
116
|
+
lookup="sf",
|
|
117
|
+
fdata=fdata,
|
|
118
|
+
upcast=False,
|
|
119
|
+
selection=st_sel,
|
|
120
|
+
)
|
|
110
121
|
ti = self.get_data(
|
|
111
|
-
self.ti_var,
|
|
112
|
-
|
|
122
|
+
self.ti_var,
|
|
123
|
+
FC.STATE_TURBINE,
|
|
124
|
+
lookup="f",
|
|
125
|
+
fdata=fdata,
|
|
126
|
+
upcast=False,
|
|
127
|
+
selection=st_sel,
|
|
128
|
+
)
|
|
113
129
|
|
|
114
130
|
k = fdata.get(
|
|
115
131
|
self.k_var, np.zeros((fdata.n_states, fdata.n_turbines), dtype=FC.DTYPE)
|
|
@@ -25,7 +25,7 @@ class PCtFile(TurbineType):
|
|
|
25
25
|
col_ct: str
|
|
26
26
|
The ct column
|
|
27
27
|
rho: float
|
|
28
|
-
The air
|
|
28
|
+
The air density for which the data is valid
|
|
29
29
|
or None for no correction
|
|
30
30
|
WSCT: str
|
|
31
31
|
The wind speed variable for ct lookup
|
|
@@ -66,7 +66,7 @@ class PCtFile(TurbineType):
|
|
|
66
66
|
col_ct: str
|
|
67
67
|
The ct column
|
|
68
68
|
rho: float, optional
|
|
69
|
-
The air
|
|
69
|
+
The air density for which the data is valid
|
|
70
70
|
or None for no correction
|
|
71
71
|
p_ct: float
|
|
72
72
|
The exponent for yaw dependency of ct
|
|
@@ -108,7 +108,7 @@ class PCtFile(TurbineType):
|
|
|
108
108
|
|
|
109
109
|
def needs_rews2(self):
|
|
110
110
|
"""
|
|
111
|
-
Returns flag for
|
|
111
|
+
Returns flag for requiring REWS2 variable
|
|
112
112
|
|
|
113
113
|
Returns
|
|
114
114
|
-------
|
|
@@ -120,7 +120,7 @@ class PCtFile(TurbineType):
|
|
|
120
120
|
|
|
121
121
|
def needs_rews3(self):
|
|
122
122
|
"""
|
|
123
|
-
Returns flag for
|
|
123
|
+
Returns flag for requiring REWS3 variable
|
|
124
124
|
|
|
125
125
|
Returns
|
|
126
126
|
-------
|
|
@@ -276,7 +276,7 @@ class PCtFile(TurbineType):
|
|
|
276
276
|
super().modify_cutin(modify_ct, modify_P)
|
|
277
277
|
|
|
278
278
|
def calculate(self, algo, mdata, fdata, st_sel):
|
|
279
|
-
"""
|
|
279
|
+
"""
|
|
280
280
|
The main model calculation.
|
|
281
281
|
|
|
282
282
|
This function is executed on a single chunk of data,
|
|
@@ -26,7 +26,7 @@ class PCtFromTwo(TurbineType):
|
|
|
26
26
|
col_ct: str
|
|
27
27
|
The ct column
|
|
28
28
|
rho: float
|
|
29
|
-
The air
|
|
29
|
+
The air density for which the data is valid
|
|
30
30
|
or None for no correction
|
|
31
31
|
WSCT: str
|
|
32
32
|
The wind speed variable for ct lookup
|
|
@@ -76,7 +76,7 @@ class PCtFromTwo(TurbineType):
|
|
|
76
76
|
col_ct: str
|
|
77
77
|
The ct column
|
|
78
78
|
rho: float, optional
|
|
79
|
-
The air
|
|
79
|
+
The air density for which the data is valid
|
|
80
80
|
or None for no correction
|
|
81
81
|
p_ct: float
|
|
82
82
|
The exponent for yaw dependency of ct
|
|
@@ -128,7 +128,7 @@ class PCtFromTwo(TurbineType):
|
|
|
128
128
|
|
|
129
129
|
def needs_rews2(self):
|
|
130
130
|
"""
|
|
131
|
-
Returns flag for
|
|
131
|
+
Returns flag for requiring REWS2 variable
|
|
132
132
|
|
|
133
133
|
Returns
|
|
134
134
|
-------
|
|
@@ -140,7 +140,7 @@ class PCtFromTwo(TurbineType):
|
|
|
140
140
|
|
|
141
141
|
def needs_rews3(self):
|
|
142
142
|
"""
|
|
143
|
-
Returns flag for
|
|
143
|
+
Returns flag for requiring REWS3 variable
|
|
144
144
|
|
|
145
145
|
Returns
|
|
146
146
|
-------
|
|
@@ -313,7 +313,7 @@ class PCtFromTwo(TurbineType):
|
|
|
313
313
|
super().modify_cutin(modify_ct, modify_P)
|
|
314
314
|
|
|
315
315
|
def calculate(self, algo, mdata, fdata, st_sel):
|
|
316
|
-
"""
|
|
316
|
+
"""
|
|
317
317
|
The main model calculation.
|
|
318
318
|
|
|
319
319
|
This function is executed on a single chunk of data,
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
import pandas as pd
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
|
|
5
|
+
from .PCt_file import PCtFile
|
|
6
|
+
from foxes.data import parse_Pct_file_name
|
|
7
|
+
import foxes.constants as FC
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class TBLFile(PCtFile):
|
|
11
|
+
"""
|
|
12
|
+
Reads turbine data from a TBL file.
|
|
13
|
+
|
|
14
|
+
Examples
|
|
15
|
+
--------
|
|
16
|
+
A TBL file is a csv file with space as separator
|
|
17
|
+
and two header lines. The followind lines denote
|
|
18
|
+
wind speed, ct, P.
|
|
19
|
+
|
|
20
|
+
- first row will be ignored
|
|
21
|
+
- second row: H D ct-stand-still rated-power-in-MW
|
|
22
|
+
- further rows: ws ct P-in-kW
|
|
23
|
+
|
|
24
|
+
For example:
|
|
25
|
+
|
|
26
|
+
45
|
|
27
|
+
175.0 290.0 0.03 22.0
|
|
28
|
+
3.0 0.820 102.9
|
|
29
|
+
3.5 0.800 444.0
|
|
30
|
+
4.0 0.810 874.7
|
|
31
|
+
4.5 0.820 1418.7
|
|
32
|
+
5.0 0.820 2100.9
|
|
33
|
+
5.5 0.830 3021.2
|
|
34
|
+
6.0 0.830 3904.7
|
|
35
|
+
6.5 0.830 5061.7
|
|
36
|
+
7.0 0.810 6379.0
|
|
37
|
+
|
|
38
|
+
:group: models.turbine_types
|
|
39
|
+
|
|
40
|
+
"""
|
|
41
|
+
|
|
42
|
+
def __init__(
|
|
43
|
+
self,
|
|
44
|
+
tbl_file,
|
|
45
|
+
rho=1.225,
|
|
46
|
+
**parameters,
|
|
47
|
+
):
|
|
48
|
+
"""
|
|
49
|
+
Constructor.
|
|
50
|
+
|
|
51
|
+
Parameters
|
|
52
|
+
----------
|
|
53
|
+
tbl_file: str
|
|
54
|
+
Path to the tbl file
|
|
55
|
+
rho: float
|
|
56
|
+
The air density for the curves
|
|
57
|
+
paramerers: dict, optional
|
|
58
|
+
Additional parameters for PCtFile class
|
|
59
|
+
|
|
60
|
+
"""
|
|
61
|
+
fpath = Path(tbl_file)
|
|
62
|
+
assert fpath.suffix == ".tbl", f"Expecting *.tbl file, got '{tbl_file}'"
|
|
63
|
+
|
|
64
|
+
meta = np.genfromtxt(fpath, skip_header=1, max_rows=1)
|
|
65
|
+
sdata = pd.read_csv(
|
|
66
|
+
fpath, sep=" ", skiprows=2, header=None, names=["ws", "ct", "P"]
|
|
67
|
+
)
|
|
68
|
+
|
|
69
|
+
super().__init__(
|
|
70
|
+
sdata,
|
|
71
|
+
col_ws="ws",
|
|
72
|
+
col_P="P",
|
|
73
|
+
col_ct="ct",
|
|
74
|
+
H=meta[0],
|
|
75
|
+
D=meta[1],
|
|
76
|
+
P_nominal=meta[3] * 1e3,
|
|
77
|
+
P_unit="kW",
|
|
78
|
+
rho=rho,
|
|
79
|
+
**parameters,
|
|
80
|
+
)
|
|
@@ -17,7 +17,7 @@ class FromLookupTable(TurbineType):
|
|
|
17
17
|
source: str or pandas.DataFrame
|
|
18
18
|
The file path, static name, or data
|
|
19
19
|
rho: float
|
|
20
|
-
The air
|
|
20
|
+
The air density for which the data is valid
|
|
21
21
|
or None for no correction
|
|
22
22
|
WSCT: str
|
|
23
23
|
The wind speed variable for ct lookup
|
|
@@ -60,7 +60,7 @@ class FromLookupTable(TurbineType):
|
|
|
60
60
|
lookup_pars: dict
|
|
61
61
|
Additional parameters for the LookupTable model
|
|
62
62
|
rho: float, optional
|
|
63
|
-
The air
|
|
63
|
+
The air density for which the data is valid
|
|
64
64
|
or None for no correction
|
|
65
65
|
p_ct: float
|
|
66
66
|
The exponent for yaw dependency of ct
|
|
@@ -119,7 +119,7 @@ class FromLookupTable(TurbineType):
|
|
|
119
119
|
|
|
120
120
|
def needs_rews2(self):
|
|
121
121
|
"""
|
|
122
|
-
Returns flag for
|
|
122
|
+
Returns flag for requiring REWS2 variable
|
|
123
123
|
|
|
124
124
|
Returns
|
|
125
125
|
-------
|
|
@@ -131,7 +131,7 @@ class FromLookupTable(TurbineType):
|
|
|
131
131
|
|
|
132
132
|
def needs_rews3(self):
|
|
133
133
|
"""
|
|
134
|
-
Returns flag for
|
|
134
|
+
Returns flag for requiring REWS3 variable
|
|
135
135
|
|
|
136
136
|
Returns
|
|
137
137
|
-------
|
|
@@ -228,7 +228,7 @@ class FromLookupTable(TurbineType):
|
|
|
228
228
|
super().modify_cutin(modify_ct, modify_P)
|
|
229
229
|
|
|
230
230
|
def calculate(self, algo, mdata, fdata, st_sel):
|
|
231
|
-
"""
|
|
231
|
+
"""
|
|
232
232
|
The main model calculation.
|
|
233
233
|
|
|
234
234
|
This function is executed on a single chunk of data,
|
|
@@ -37,7 +37,7 @@ class NullType(TurbineType):
|
|
|
37
37
|
|
|
38
38
|
def needs_rews2(self):
|
|
39
39
|
"""
|
|
40
|
-
Returns flag for
|
|
40
|
+
Returns flag for requiring REWS2 variable
|
|
41
41
|
|
|
42
42
|
Returns
|
|
43
43
|
-------
|
|
@@ -49,7 +49,7 @@ class NullType(TurbineType):
|
|
|
49
49
|
|
|
50
50
|
def needs_rews3(self):
|
|
51
51
|
"""
|
|
52
|
-
Returns flag for
|
|
52
|
+
Returns flag for requiring REWS3 variable
|
|
53
53
|
|
|
54
54
|
Returns
|
|
55
55
|
-------
|
|
@@ -77,7 +77,7 @@ class NullType(TurbineType):
|
|
|
77
77
|
return []
|
|
78
78
|
|
|
79
79
|
def calculate(self, algo, mdata, fdata, st_sel):
|
|
80
|
-
"""
|
|
80
|
+
"""
|
|
81
81
|
The main model calculation.
|
|
82
82
|
|
|
83
83
|
This function is executed on a single chunk of data,
|
|
@@ -37,9 +37,9 @@ class WsRho2PCtFromTwo(TurbineType):
|
|
|
37
37
|
rpars_ct: dict, optional
|
|
38
38
|
Parameters for pandas ct file reading
|
|
39
39
|
ipars_P: dict, optional
|
|
40
|
-
Parameters for scipy.interpolate.interpn
|
|
40
|
+
Parameters for scipy.interpolate.interpn
|
|
41
41
|
ipars_ct: dict, optional
|
|
42
|
-
Parameters for scipy.interpolate.interpn
|
|
42
|
+
Parameters for scipy.interpolate.interpn
|
|
43
43
|
|
|
44
44
|
:group: models.turbine_types
|
|
45
45
|
|
|
@@ -81,9 +81,9 @@ class WsRho2PCtFromTwo(TurbineType):
|
|
|
81
81
|
pd_file_read_pars_ct: dict
|
|
82
82
|
Parameters for pandas ct file reading
|
|
83
83
|
interpn_pars_P: dict, optional
|
|
84
|
-
Parameters for scipy.interpolate.interpn
|
|
84
|
+
Parameters for scipy.interpolate.interpn
|
|
85
85
|
interpn_pars_ct: dict, optional
|
|
86
|
-
Parameters for scipy.interpolate.interpn
|
|
86
|
+
Parameters for scipy.interpolate.interpn
|
|
87
87
|
parameters: dict, optional
|
|
88
88
|
Additional parameters for TurbineType class
|
|
89
89
|
|
|
@@ -117,7 +117,7 @@ class WsRho2PCtFromTwo(TurbineType):
|
|
|
117
117
|
|
|
118
118
|
def needs_rews2(self):
|
|
119
119
|
"""
|
|
120
|
-
Returns flag for
|
|
120
|
+
Returns flag for requiring REWS2 variable
|
|
121
121
|
|
|
122
122
|
Returns
|
|
123
123
|
-------
|
|
@@ -129,7 +129,7 @@ class WsRho2PCtFromTwo(TurbineType):
|
|
|
129
129
|
|
|
130
130
|
def needs_rews3(self):
|
|
131
131
|
"""
|
|
132
|
-
Returns flag for
|
|
132
|
+
Returns flag for requiring REWS3 variable
|
|
133
133
|
|
|
134
134
|
Returns
|
|
135
135
|
-------
|
|
@@ -229,7 +229,7 @@ class WsRho2PCtFromTwo(TurbineType):
|
|
|
229
229
|
print()
|
|
230
230
|
|
|
231
231
|
def calculate(self, algo, mdata, fdata, st_sel):
|
|
232
|
-
"""
|
|
232
|
+
"""
|
|
233
233
|
The main model calculation.
|
|
234
234
|
|
|
235
235
|
This function is executed on a single chunk of data,
|