foxes 1.4__py3-none-any.whl → 1.5__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 +1 -1
- examples/field_data_nc/run.py +1 -1
- examples/streamline_wakes/run.py +2 -2
- examples/yawed_wake/run.py +3 -1
- foxes/algorithms/downwind/downwind.py +5 -5
- foxes/algorithms/downwind/models/init_farm_data.py +58 -28
- foxes/algorithms/downwind/models/set_amb_farm_results.py +1 -1
- foxes/core/algorithm.py +5 -5
- foxes/core/data.py +75 -4
- foxes/core/data_calc_model.py +4 -2
- foxes/core/engine.py +33 -40
- foxes/core/farm_data_model.py +16 -13
- foxes/core/model.py +19 -1
- foxes/core/point_data_model.py +19 -14
- foxes/core/rotor_model.py +1 -0
- foxes/core/wake_deflection.py +3 -3
- foxes/data/states/point_cloud_100.nc +0 -0
- foxes/data/states/weibull_cloud_4.nc +0 -0
- foxes/data/states/weibull_grid.nc +0 -0
- foxes/engines/dask.py +3 -6
- foxes/engines/default.py +2 -2
- foxes/engines/numpy.py +11 -10
- foxes/engines/pool.py +20 -11
- foxes/engines/single.py +8 -6
- foxes/input/farm_layout/__init__.py +1 -0
- foxes/input/farm_layout/from_arrays.py +68 -0
- foxes/input/states/__init__.py +7 -1
- foxes/input/states/dataset_states.py +710 -0
- foxes/input/states/field_data.py +531 -0
- foxes/input/states/multi_height.py +2 -0
- foxes/input/states/one_point_flow.py +1 -0
- foxes/input/states/point_cloud_data.py +618 -0
- foxes/input/states/scan.py +2 -0
- foxes/input/states/single.py +2 -0
- foxes/input/states/states_table.py +13 -23
- foxes/input/states/weibull_sectors.py +182 -77
- foxes/input/states/wrg_states.py +1 -1
- foxes/input/yaml/dict.py +25 -24
- foxes/input/yaml/windio/read_attributes.py +40 -27
- foxes/input/yaml/windio/read_farm.py +12 -10
- foxes/input/yaml/windio/read_outputs.py +25 -15
- foxes/input/yaml/windio/read_site.py +121 -12
- foxes/input/yaml/windio/windio.py +22 -10
- foxes/input/yaml/yaml.py +1 -0
- foxes/models/model_book.py +16 -15
- foxes/models/rotor_models/__init__.py +1 -0
- foxes/models/rotor_models/centre.py +1 -1
- foxes/models/rotor_models/direct_infusion.py +241 -0
- foxes/models/turbine_models/calculator.py +16 -3
- foxes/models/turbine_models/kTI_model.py +1 -0
- foxes/models/turbine_models/lookup_table.py +2 -0
- foxes/models/turbine_models/power_mask.py +1 -0
- foxes/models/turbine_models/rotor_centre_calc.py +2 -0
- foxes/models/turbine_models/sector_management.py +1 -0
- foxes/models/turbine_models/set_farm_vars.py +3 -8
- foxes/models/turbine_models/table_factors.py +2 -0
- foxes/models/turbine_models/thrust2ct.py +1 -0
- foxes/models/turbine_models/yaw2yawm.py +2 -0
- foxes/models/turbine_models/yawm2yaw.py +2 -0
- foxes/models/turbine_types/PCt_file.py +2 -4
- foxes/models/turbine_types/PCt_from_two.py +1 -0
- foxes/models/turbine_types/__init__.py +1 -0
- foxes/models/turbine_types/calculator_type.py +123 -0
- foxes/models/turbine_types/null_type.py +1 -0
- foxes/models/turbine_types/wsrho2PCt_from_two.py +2 -0
- foxes/models/turbine_types/wsti2PCt_from_two.py +3 -1
- foxes/output/farm_layout.py +2 -0
- foxes/output/farm_results_eval.py +4 -1
- foxes/output/flow_plots_2d/flow_plots.py +18 -0
- foxes/output/flow_plots_2d/get_fig.py +1 -0
- foxes/output/output.py +6 -1
- foxes/output/results_writer.py +1 -1
- foxes/output/rose_plot.py +10 -0
- foxes/output/rotor_point_plots.py +3 -0
- foxes/output/state_turbine_map.py +3 -0
- foxes/output/turbine_type_curves.py +3 -0
- foxes/utils/dict.py +46 -34
- foxes/utils/factory.py +2 -2
- {foxes-1.4.dist-info → foxes-1.5.dist-info}/METADATA +32 -52
- {foxes-1.4.dist-info → foxes-1.5.dist-info}/RECORD +84 -76
- foxes/input/states/field_data_nc.py +0 -833
- {foxes-1.4.dist-info → foxes-1.5.dist-info}/WHEEL +0 -0
- {foxes-1.4.dist-info → foxes-1.5.dist-info}/entry_points.txt +0 -0
- {foxes-1.4.dist-info → foxes-1.5.dist-info}/licenses/LICENSE +0 -0
- {foxes-1.4.dist-info → foxes-1.5.dist-info}/top_level.txt +0 -0
foxes/models/model_book.py
CHANGED
|
@@ -85,12 +85,13 @@ class ModelBook:
|
|
|
85
85
|
Path to power/ct curve file, for creation
|
|
86
86
|
of default turbine type model
|
|
87
87
|
"""
|
|
88
|
-
self.point_models = FDict(
|
|
88
|
+
self.point_models = FDict(_name="point_models")
|
|
89
89
|
self.point_models["tke2ti"] = fm.point_models.TKE2TI()
|
|
90
90
|
self.point_models["ustar2ti"] = fm.point_models.Ustar2TI()
|
|
91
91
|
|
|
92
|
-
self.rotor_models = FDict(
|
|
92
|
+
self.rotor_models = FDict(_name="rotor_models")
|
|
93
93
|
self.rotor_models["centre"] = fm.rotor_models.CentreRotor()
|
|
94
|
+
self.rotor_models["direct_mdata"] = fm.rotor_models.DirectMDataInfusion()
|
|
94
95
|
|
|
95
96
|
def _n2n(n2):
|
|
96
97
|
n2 = float(n2)
|
|
@@ -132,7 +133,7 @@ class ModelBook:
|
|
|
132
133
|
hints={"n": "(Number of vertical levels)"},
|
|
133
134
|
)
|
|
134
135
|
|
|
135
|
-
self.turbine_types = FDict(
|
|
136
|
+
self.turbine_types = FDict(_name="turbine_types")
|
|
136
137
|
self.turbine_types["null_type"] = fm.turbine_types.NullType()
|
|
137
138
|
self.turbine_types["NREL5MW"] = fm.turbine_types.PCtFile(
|
|
138
139
|
"NREL-5MW-D126-H90.csv", rho=1.225
|
|
@@ -150,7 +151,7 @@ class ModelBook:
|
|
|
150
151
|
self.turbine_types["Pct"] = fm.turbine_types.PCtFile(Pct_file)
|
|
151
152
|
|
|
152
153
|
self.turbine_models = FDict(
|
|
153
|
-
|
|
154
|
+
_name="turbine_models",
|
|
154
155
|
kTI=fm.turbine_models.kTI(),
|
|
155
156
|
kTI_amb=fm.turbine_models.kTI(ti_var=FV.AMB_TI),
|
|
156
157
|
thrust2ct=fm.turbine_models.Thrust2Ct(),
|
|
@@ -203,7 +204,7 @@ class ModelBook:
|
|
|
203
204
|
)
|
|
204
205
|
|
|
205
206
|
self.farm_models = FDict(
|
|
206
|
-
|
|
207
|
+
_name="farm_models",
|
|
207
208
|
**{
|
|
208
209
|
f"farm_{mname}": fm.farm_models.Turbine2FarmModel(m)
|
|
209
210
|
for mname, m in self.turbine_models.items()
|
|
@@ -211,12 +212,12 @@ class ModelBook:
|
|
|
211
212
|
)
|
|
212
213
|
|
|
213
214
|
self.farm_controllers = FDict(
|
|
214
|
-
|
|
215
|
+
_name="farm_controllers",
|
|
215
216
|
basic_ctrl=fm.farm_controllers.BasicFarmController(),
|
|
216
217
|
)
|
|
217
218
|
|
|
218
219
|
self.partial_wakes = FDict(
|
|
219
|
-
|
|
220
|
+
_name="partial_wakes",
|
|
220
221
|
rotor_points=fm.partial_wakes.RotorPoints(),
|
|
221
222
|
top_hat=fm.partial_wakes.PartialTopHat(),
|
|
222
223
|
centre=fm.partial_wakes.PartialCentre(),
|
|
@@ -236,7 +237,7 @@ class ModelBook:
|
|
|
236
237
|
)
|
|
237
238
|
|
|
238
239
|
self.wake_deflections = FDict(
|
|
239
|
-
|
|
240
|
+
_name="wake_deflections",
|
|
240
241
|
no_deflection=fm.wake_deflections.NoDeflection(),
|
|
241
242
|
Bastankhah2016=fm.wake_deflections.Bastankhah2016Deflection(),
|
|
242
243
|
Jimenez=fm.wake_deflections.JimenezDeflection(rotate=True),
|
|
@@ -303,7 +304,7 @@ class ModelBook:
|
|
|
303
304
|
)
|
|
304
305
|
|
|
305
306
|
self.wake_frames = FDict(
|
|
306
|
-
|
|
307
|
+
_name="wake_frames",
|
|
307
308
|
rotor_wd=fm.wake_frames.RotorWD(),
|
|
308
309
|
rotor_wd_farmo=fm.wake_frames.FarmOrder(),
|
|
309
310
|
)
|
|
@@ -363,7 +364,7 @@ class ModelBook:
|
|
|
363
364
|
)
|
|
364
365
|
|
|
365
366
|
self.wake_superpositions = FDict(
|
|
366
|
-
|
|
367
|
+
_name="wake_superpositions",
|
|
367
368
|
ws_linear=fm.wake_superpositions.WSLinear(scale_amb=False),
|
|
368
369
|
ws_linear_lim=fm.wake_superpositions.WSLinear(
|
|
369
370
|
scale_amb=False, lim_low=1e-4
|
|
@@ -407,11 +408,11 @@ class ModelBook:
|
|
|
407
408
|
vector_amb=fm.wake_superpositions.WindVectorLinear(scale_amb=True),
|
|
408
409
|
)
|
|
409
410
|
|
|
410
|
-
self.axial_induction = FDict(
|
|
411
|
+
self.axial_induction = FDict(_name="induction_models")
|
|
411
412
|
self.axial_induction["Betz"] = fm.axial_induction.BetzAxialInduction()
|
|
412
413
|
self.axial_induction["Madsen"] = fm.axial_induction.MadsenAxialInduction()
|
|
413
414
|
|
|
414
|
-
self.wake_models = FDict(
|
|
415
|
+
self.wake_models = FDict(_name="wake_models")
|
|
415
416
|
|
|
416
417
|
self.wake_models.add_k_factory(
|
|
417
418
|
fm.wake_models.wind.JensenWake,
|
|
@@ -616,7 +617,7 @@ class ModelBook:
|
|
|
616
617
|
},
|
|
617
618
|
)
|
|
618
619
|
|
|
619
|
-
self.ground_models = FDict(
|
|
620
|
+
self.ground_models = FDict(_name="ground_models")
|
|
620
621
|
self.ground_models["no_ground"] = fm.ground_models.NoGround()
|
|
621
622
|
self.ground_models["ground_mirror"] = fm.ground_models.GroundMirror()
|
|
622
623
|
self.ground_models.add_factory(
|
|
@@ -629,7 +630,7 @@ class ModelBook:
|
|
|
629
630
|
)
|
|
630
631
|
|
|
631
632
|
self.sources = FDict(
|
|
632
|
-
|
|
633
|
+
_name="sources",
|
|
633
634
|
point_models=self.point_models,
|
|
634
635
|
rotor_models=self.rotor_models,
|
|
635
636
|
turbine_types=self.turbine_types,
|
|
@@ -645,7 +646,7 @@ class ModelBook:
|
|
|
645
646
|
ground_models=self.ground_models,
|
|
646
647
|
)
|
|
647
648
|
self.base_classes = FDict(
|
|
648
|
-
|
|
649
|
+
_name="base_classes",
|
|
649
650
|
point_models=PointDataModel,
|
|
650
651
|
rotor_models=RotorModel,
|
|
651
652
|
turbine_types=TurbineType,
|
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
|
|
3
|
+
from foxes.core import TData
|
|
4
|
+
import foxes.variables as FV
|
|
5
|
+
import foxes.constants as FC
|
|
6
|
+
|
|
7
|
+
from .centre import CentreRotor
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class DirectMDataInfusion(CentreRotor):
|
|
11
|
+
"""
|
|
12
|
+
Direct data infusion of data stored under mdata.
|
|
13
|
+
|
|
14
|
+
Attributes
|
|
15
|
+
----------
|
|
16
|
+
svars2mdvars: dict
|
|
17
|
+
A mapping of state variables to mdata variables.
|
|
18
|
+
mdata_vars: list of str
|
|
19
|
+
The mdata variables to be used for infusion. By default,
|
|
20
|
+
all mdata variables are searched.
|
|
21
|
+
turbine_coord: str, optional
|
|
22
|
+
The mdata coordinate that represents turbine names. By default,
|
|
23
|
+
the second coordinate is used as a candidate if the mdata variable
|
|
24
|
+
has three dimensions.
|
|
25
|
+
|
|
26
|
+
:group: models.turbine_types
|
|
27
|
+
|
|
28
|
+
"""
|
|
29
|
+
|
|
30
|
+
def __init__(
|
|
31
|
+
self,
|
|
32
|
+
svars2mdvars=None,
|
|
33
|
+
mdata_vars=None,
|
|
34
|
+
turbine_coord=None,
|
|
35
|
+
**kwargs,
|
|
36
|
+
):
|
|
37
|
+
"""
|
|
38
|
+
Constructor.
|
|
39
|
+
|
|
40
|
+
Parameters
|
|
41
|
+
----------
|
|
42
|
+
svars2mdvars: dict, optional
|
|
43
|
+
A mapping of state variables to mdata variables.
|
|
44
|
+
mdata_vars: list of str, optional
|
|
45
|
+
The mdata variables to be used for infusion. By default,
|
|
46
|
+
all mdata variables are searched.
|
|
47
|
+
turbine_coord: str, optional
|
|
48
|
+
The mdata coordinate that represents turbine names. By default,
|
|
49
|
+
the second coordinate is used as a candidate if the mdata variable
|
|
50
|
+
has three dimensions.
|
|
51
|
+
kwargs: dict, optional
|
|
52
|
+
Additional parameters for RotorModel class
|
|
53
|
+
|
|
54
|
+
"""
|
|
55
|
+
super().__init__(**kwargs)
|
|
56
|
+
self.svars2mdvars = svars2mdvars
|
|
57
|
+
self.mdata_vars = mdata_vars
|
|
58
|
+
self.turbine_coord = turbine_coord
|
|
59
|
+
|
|
60
|
+
def output_farm_vars(self, algo):
|
|
61
|
+
"""
|
|
62
|
+
The variables which are being modified by the model.
|
|
63
|
+
|
|
64
|
+
Parameters
|
|
65
|
+
----------
|
|
66
|
+
algo: foxes.core.Algorithm
|
|
67
|
+
The calculation algorithm
|
|
68
|
+
|
|
69
|
+
Returns
|
|
70
|
+
-------
|
|
71
|
+
output_vars: list of str
|
|
72
|
+
The output variable names
|
|
73
|
+
|
|
74
|
+
"""
|
|
75
|
+
if self.svars2mdvars is None:
|
|
76
|
+
self.svars2mdvars = {v: v for v in algo.states.output_point_vars(algo)}
|
|
77
|
+
|
|
78
|
+
if self.calc_vars is None:
|
|
79
|
+
vrs = list(self.svars2mdvars.keys())
|
|
80
|
+
assert FV.WEIGHT not in vrs, (
|
|
81
|
+
f"Rotor '{self.name}': svars2mdvars keys {vrs} contain '{FV.WEIGHT}', please remove"
|
|
82
|
+
)
|
|
83
|
+
|
|
84
|
+
if FV.WS in vrs:
|
|
85
|
+
self.calc_vars = [FV.REWS] + [v for v in vrs if v != FV.WS]
|
|
86
|
+
else:
|
|
87
|
+
self.calc_vars = vrs
|
|
88
|
+
|
|
89
|
+
if algo.farm_controller.needs_rews2() and FV.REWS2 not in self.calc_vars:
|
|
90
|
+
self.calc_vars.append(FV.REWS2)
|
|
91
|
+
if algo.farm_controller.needs_rews3() and FV.REWS3 not in self.calc_vars:
|
|
92
|
+
self.calc_vars.append(FV.REWS3)
|
|
93
|
+
|
|
94
|
+
self.calc_vars = sorted(self.calc_vars)
|
|
95
|
+
|
|
96
|
+
if FV.WEIGHT not in self.calc_vars:
|
|
97
|
+
self.calc_vars.append(FV.WEIGHT)
|
|
98
|
+
if FV.WEIGHT not in self.svars2mdvars:
|
|
99
|
+
self.svars2mdvars[FV.WEIGHT] = FV.WEIGHT
|
|
100
|
+
|
|
101
|
+
return self.calc_vars
|
|
102
|
+
|
|
103
|
+
def calculate(
|
|
104
|
+
self,
|
|
105
|
+
algo,
|
|
106
|
+
mdata,
|
|
107
|
+
fdata,
|
|
108
|
+
rpoints=None,
|
|
109
|
+
rpoint_weights=None,
|
|
110
|
+
store=False,
|
|
111
|
+
downwind_index=None,
|
|
112
|
+
):
|
|
113
|
+
"""
|
|
114
|
+
Calculate ambient rotor effective results.
|
|
115
|
+
|
|
116
|
+
Parameters
|
|
117
|
+
----------
|
|
118
|
+
algo: foxes.core.Algorithm
|
|
119
|
+
The calculation algorithm
|
|
120
|
+
mdata: foxes.core.MData
|
|
121
|
+
The model data
|
|
122
|
+
fdata: foxes.core.FData
|
|
123
|
+
The farm data
|
|
124
|
+
rpoints: numpy.ndarray, optional
|
|
125
|
+
The rotor points, or None for automatic for
|
|
126
|
+
this rotor. Shape: (n_states, n_turbines, n_rpoints, 3)
|
|
127
|
+
rpoint_weights: numpy.ndarray, optional
|
|
128
|
+
The rotor point weights, or None for automatic
|
|
129
|
+
for this rotor. Shape: (n_rpoints,)
|
|
130
|
+
store: bool, optional
|
|
131
|
+
Flag for storing ambient rotor point results
|
|
132
|
+
downwind_index: int, optional
|
|
133
|
+
Only compute for index in the downwind order
|
|
134
|
+
|
|
135
|
+
Returns
|
|
136
|
+
-------
|
|
137
|
+
results: dict
|
|
138
|
+
results dict. Keys: Variable name str. Values:
|
|
139
|
+
numpy.ndarray with results, shape: (n_states, n_turbines)
|
|
140
|
+
|
|
141
|
+
"""
|
|
142
|
+
self.ensure_output_vars(algo, fdata)
|
|
143
|
+
|
|
144
|
+
if rpoints is None:
|
|
145
|
+
rpoints = mdata.get(
|
|
146
|
+
FC.ROTOR_POINTS, self.get_rotor_points(algo, mdata, fdata)
|
|
147
|
+
)
|
|
148
|
+
if downwind_index is not None:
|
|
149
|
+
rpoints = rpoints[:, downwind_index, None]
|
|
150
|
+
if rpoint_weights is None:
|
|
151
|
+
rpoint_weights = mdata.get_item(FC.TWEIGHTS, self.rotor_point_weights())
|
|
152
|
+
|
|
153
|
+
tdata = TData.from_tpoints(rpoints, rpoint_weights)
|
|
154
|
+
sres = {}
|
|
155
|
+
mdvs = self.mdata_vars if self.mdata_vars is not None else list(mdata.keys())
|
|
156
|
+
for v, w in self.svars2mdvars.items():
|
|
157
|
+
tdata.add(
|
|
158
|
+
v,
|
|
159
|
+
data=np.full_like(rpoints[..., 0], np.nan),
|
|
160
|
+
dims=(FC.STATE, FC.TARGET, FC.TPOINT),
|
|
161
|
+
)
|
|
162
|
+
|
|
163
|
+
# check fixed variables
|
|
164
|
+
if hasattr(algo.states, "fixed_vars") and v in algo.states.fixed_vars:
|
|
165
|
+
tdata[v][:] = algo.states.fixed_vars[v]
|
|
166
|
+
sres[v] = tdata[v]
|
|
167
|
+
continue
|
|
168
|
+
|
|
169
|
+
# search in mdata variables
|
|
170
|
+
tcoord = self.turbine_coord
|
|
171
|
+
for mdv in mdvs:
|
|
172
|
+
assert mdv in mdata and mdv in mdata.dims, (
|
|
173
|
+
f"Rotor '{self.name}': mdata variable '{mdv}' not found in mdata {list(mdata.keys())} with dims {list(mdata.dims.keys())}"
|
|
174
|
+
)
|
|
175
|
+
mdat = mdata[mdv]
|
|
176
|
+
dims = mdata.dims[mdv]
|
|
177
|
+
|
|
178
|
+
# skip coordinates in the search:
|
|
179
|
+
if dims == (mdv,):
|
|
180
|
+
continue
|
|
181
|
+
|
|
182
|
+
# find variable index in last data array dimension
|
|
183
|
+
vc = dims[-1]
|
|
184
|
+
assert vc in mdata and vc in mdata.dims and mdata.dims[vc] == (vc,), (
|
|
185
|
+
f"Rotor '{self.name}': mdata coordinate '{vc}' not in mdata or wrong dimensions {mdata.dims}, expected '{(vc,)}'"
|
|
186
|
+
)
|
|
187
|
+
vrs = list(mdata[vc])
|
|
188
|
+
if w in vrs:
|
|
189
|
+
i = vrs.index(w)
|
|
190
|
+
mdat = mdat[..., i]
|
|
191
|
+
dims = dims[:-1]
|
|
192
|
+
|
|
193
|
+
# pure state dependent variable
|
|
194
|
+
if dims == (FC.STATE,):
|
|
195
|
+
tdata[v][:] = mdat[:, None, None]
|
|
196
|
+
|
|
197
|
+
# state and turbine dependent variable
|
|
198
|
+
elif len(dims) == 2 and dims[0] == FC.STATE:
|
|
199
|
+
assert mdat.shape[1] == mdata.n_turbines, (
|
|
200
|
+
f"Rotor '{self.name}': mdata variable '{mdv}' has dimensions {dims} and unexpected shape {mdat.shape} for variable '{w}', expected ({mdata.n_states}, {mdata.n_turbines}) for this wind farm with {mdata.n_turbines} turbines"
|
|
201
|
+
)
|
|
202
|
+
if tcoord is None:
|
|
203
|
+
tcoord = dims[1]
|
|
204
|
+
assert dims[1] == tcoord, (
|
|
205
|
+
f"Rotor '{self.name}': mdata variable '{mdv}' has unexpected dimensions {dims} for variable '{w}', expected ({FC.STATE}, {tcoord})"
|
|
206
|
+
)
|
|
207
|
+
|
|
208
|
+
tdata[v][:] = mdat[:, :, None]
|
|
209
|
+
|
|
210
|
+
else:
|
|
211
|
+
if tcoord is None:
|
|
212
|
+
tcoord = "<turbine>"
|
|
213
|
+
raise ValueError(
|
|
214
|
+
f"Rotor '{self.name}': mdata variable '{mdv}' has unexpected dimensions {dims} for variable '{w}' at position {i}, expected ({FC.STATE},) or ({FC.STATE}, {tcoord})"
|
|
215
|
+
)
|
|
216
|
+
|
|
217
|
+
sres[v] = tdata[v]
|
|
218
|
+
break
|
|
219
|
+
|
|
220
|
+
if v not in sres:
|
|
221
|
+
raise ValueError(
|
|
222
|
+
f"Rotor '{self.name}': mdata variable '{w}' not found in any of the mdata variables {mdvs}"
|
|
223
|
+
)
|
|
224
|
+
|
|
225
|
+
if store:
|
|
226
|
+
algo.add_to_chunk_store(FC.ROTOR_POINTS, rpoints, mdata=mdata)
|
|
227
|
+
algo.add_to_chunk_store(FC.ROTOR_WEIGHTS, rpoint_weights, mdata=mdata)
|
|
228
|
+
algo.add_to_chunk_store(FC.AMB_ROTOR_RES, sres, mdata=mdata)
|
|
229
|
+
algo.add_to_chunk_store(FC.WEIGHT_RES, tdata[FV.WEIGHT], mdata=mdata)
|
|
230
|
+
|
|
231
|
+
self.eval_rpoint_results(
|
|
232
|
+
algo,
|
|
233
|
+
mdata,
|
|
234
|
+
fdata,
|
|
235
|
+
tdata,
|
|
236
|
+
rpoint_weights,
|
|
237
|
+
downwind_index,
|
|
238
|
+
copy_to_ambient=True,
|
|
239
|
+
)
|
|
240
|
+
|
|
241
|
+
return {v: fdata[v] for v in self.output_farm_vars(algo)}
|
|
@@ -12,11 +12,17 @@ class Calculator(TurbineModel):
|
|
|
12
12
|
out_vars: list of str
|
|
13
13
|
The output variables
|
|
14
14
|
func: Function
|
|
15
|
-
The function: f(in0, in1, ...,
|
|
15
|
+
The function: f(in0, in1, ..., algo, mdata, fdata, st_sel) -> (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).
|
|
19
19
|
|
|
20
|
+
Beware that the turbine ordering in fdata is in downwind order,
|
|
21
|
+
hence external data X of shape (n_states, n_turbines) in farm order
|
|
22
|
+
needs to be reordered by X[ssel, order] with
|
|
23
|
+
ssel = fdata[FV.ORDER_SSEL], order = fdata[FV.ORDER]
|
|
24
|
+
before using it in combination with fdata variables.
|
|
25
|
+
|
|
20
26
|
:group: models.turbine_models
|
|
21
27
|
|
|
22
28
|
"""
|
|
@@ -32,10 +38,16 @@ class Calculator(TurbineModel):
|
|
|
32
38
|
out_vars: list of str
|
|
33
39
|
The output variables
|
|
34
40
|
func: Function
|
|
35
|
-
The function: f(in0, in1, ...,
|
|
41
|
+
The function: f(in0, in1, ..., algo, mdata, fdata, st_sel) -> (out0, out1, ...)
|
|
36
42
|
where inX and outY are numpy.ndarrays and
|
|
37
43
|
st_sel is the state-turbine selection slice or array.
|
|
38
44
|
All arrays have shape (n_states, n_turbines).
|
|
45
|
+
|
|
46
|
+
Beware that the turbine ordering in fdata is in downwind order,
|
|
47
|
+
hence external data X of shape (n_states, n_turbines) in farm order
|
|
48
|
+
needs to be reordered by X[ssel, order] with
|
|
49
|
+
ssel = fdata[FV.ORDER_SSEL], order = fdata[FV.ORDER]
|
|
50
|
+
before using it in combination with fdata variables.
|
|
39
51
|
kwargs: dict, optional
|
|
40
52
|
Additional arguments for TurbineModel
|
|
41
53
|
|
|
@@ -92,7 +104,8 @@ class Calculator(TurbineModel):
|
|
|
92
104
|
Values: numpy.ndarray with shape (n_states, n_turbines)
|
|
93
105
|
|
|
94
106
|
"""
|
|
107
|
+
self.ensure_output_vars(algo, fdata)
|
|
95
108
|
ins = [fdata[v] if v in fdata else mdata[v] for v in self.in_vars]
|
|
96
|
-
outs = self.func(*ins, st_sel=st_sel)
|
|
109
|
+
outs = self.func(*ins, algo=algo, mdata=mdata, fdata=fdata, st_sel=st_sel)
|
|
97
110
|
|
|
98
111
|
return {v: outs[vi] for vi, v in enumerate(self.out_vars)}
|
|
@@ -268,20 +268,15 @@ class SetFarmVars(TurbineModel):
|
|
|
268
268
|
Values: numpy.ndarray with shape (n_states, n_turbines)
|
|
269
269
|
|
|
270
270
|
"""
|
|
271
|
+
self.ensure_output_vars(algo, fdata)
|
|
272
|
+
|
|
271
273
|
i0 = mdata.states_i0(counter=True)
|
|
272
274
|
if not self.once or i0 not in self.__once_done:
|
|
273
|
-
if self.pre_rotor:
|
|
274
|
-
order = np.s_[:]
|
|
275
|
-
ssel = np.s_[:]
|
|
276
|
-
else:
|
|
277
|
-
order = fdata[FV.ORDER]
|
|
278
|
-
ssel = fdata[FV.ORDER_SSEL]
|
|
279
|
-
|
|
280
275
|
bsel = np.zeros((fdata.n_states, fdata.n_turbines), dtype=bool)
|
|
281
276
|
bsel[st_sel] = True
|
|
282
277
|
|
|
283
278
|
for v in self.vars:
|
|
284
|
-
data = mdata[self.var(v)]
|
|
279
|
+
data = mdata[self.var(v)]
|
|
285
280
|
hsel = ~np.isnan(data)
|
|
286
281
|
tsel = bsel & hsel
|
|
287
282
|
|
|
@@ -143,6 +143,8 @@ class TableFactors(TurbineModel):
|
|
|
143
143
|
Values: numpy.ndarray with shape (n_states, n_turbines)
|
|
144
144
|
|
|
145
145
|
"""
|
|
146
|
+
self.ensure_output_vars(algo, fdata)
|
|
147
|
+
|
|
146
148
|
n_sel = np.sum(st_sel)
|
|
147
149
|
qts = np.zeros((n_sel, 2), dtype=config.dtype_double)
|
|
148
150
|
qts[:, 0] = fdata[self.row_var][st_sel]
|
|
@@ -300,6 +300,7 @@ class PCtFile(TurbineType):
|
|
|
300
300
|
Values: numpy.ndarray with shape (n_states, n_turbines)
|
|
301
301
|
|
|
302
302
|
"""
|
|
303
|
+
self.ensure_output_vars(algo, fdata)
|
|
303
304
|
rews2 = fdata[self.WSCT][st_sel]
|
|
304
305
|
rews3 = fdata[self.WSP][st_sel]
|
|
305
306
|
|
|
@@ -330,10 +331,7 @@ class PCtFile(TurbineType):
|
|
|
330
331
|
rews3 *= (cosm**self.p_P) ** (1.0 / 3.0)
|
|
331
332
|
del yawm, cosm
|
|
332
333
|
|
|
333
|
-
out = {
|
|
334
|
-
FV.P: fdata[FV.P],
|
|
335
|
-
FV.CT: fdata[FV.CT],
|
|
336
|
-
}
|
|
334
|
+
out = {FV.P: fdata[FV.P], FV.CT: fdata[FV.CT]}
|
|
337
335
|
|
|
338
336
|
out[FV.P][st_sel] = np.interp(
|
|
339
337
|
rews3, self.data_ws, self.data_P, left=0.0, right=0.0
|
|
@@ -11,3 +11,4 @@ from .wsrho2PCt_from_two import WsRho2PCtFromTwo as WsRho2PCtFromTwo
|
|
|
11
11
|
from .wsti2PCt_from_two import WsTI2PCtFromTwo as WsTI2PCtFromTwo
|
|
12
12
|
from .lookup import FromLookupTable as FromLookupTable
|
|
13
13
|
from .TBL_file import TBLFile as TBLFile
|
|
14
|
+
from .calculator_type import CalculatorType as CalculatorType
|