foxes 1.4__py3-none-any.whl → 1.5.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 +1 -1
- examples/abl_states/run.py +58 -56
- examples/dyn_wakes/run.py +110 -118
- examples/field_data_nc/run.py +23 -21
- examples/multi_height/run.py +8 -6
- examples/scan_row/run.py +89 -87
- examples/sector_management/run.py +40 -38
- examples/states_lookup_table/run.py +6 -4
- examples/streamline_wakes/run.py +10 -8
- examples/timelines/run.py +100 -98
- examples/timeseries/run.py +71 -76
- examples/wind_rose/run.py +27 -25
- examples/yawed_wake/run.py +85 -81
- 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 +6 -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 +21 -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/utils/xarray_utils.py +20 -12
- {foxes-1.4.dist-info → foxes-1.5.1.dist-info}/METADATA +32 -52
- {foxes-1.4.dist-info → foxes-1.5.1.dist-info}/RECORD +94 -86
- foxes/input/states/field_data_nc.py +0 -833
- {foxes-1.4.dist-info → foxes-1.5.1.dist-info}/WHEEL +0 -0
- {foxes-1.4.dist-info → foxes-1.5.1.dist-info}/entry_points.txt +0 -0
- {foxes-1.4.dist-info → foxes-1.5.1.dist-info}/licenses/LICENSE +0 -0
- {foxes-1.4.dist-info → foxes-1.5.1.dist-info}/top_level.txt +0 -0
examples/yawed_wake/run.py
CHANGED
|
@@ -82,7 +82,9 @@ if __name__ == "__main__":
|
|
|
82
82
|
|
|
83
83
|
# set turbines in yaw
|
|
84
84
|
yawm = np.array([[args.yawm, args.yawm2]])
|
|
85
|
-
mbook.turbine_models["set_yawm"] = foxes.models.turbine_models.SetFarmVars(
|
|
85
|
+
mbook.turbine_models["set_yawm"] = foxes.models.turbine_models.SetFarmVars(
|
|
86
|
+
pre_rotor=True
|
|
87
|
+
)
|
|
86
88
|
mbook.turbine_models["set_yawm"].add_var(FV.YAWM, yawm)
|
|
87
89
|
|
|
88
90
|
# create states
|
|
@@ -112,93 +114,95 @@ if __name__ == "__main__":
|
|
|
112
114
|
wake_deflection=args.deflection,
|
|
113
115
|
partial_wakes=args.pwakes,
|
|
114
116
|
mbook=mbook,
|
|
115
|
-
|
|
117
|
+
)
|
|
118
|
+
|
|
119
|
+
with foxes.Engine.new(
|
|
120
|
+
engine_type=args.engine,
|
|
116
121
|
n_procs=args.n_cpus,
|
|
117
122
|
chunk_size_states=args.chunksize_states,
|
|
118
123
|
chunk_size_points=args.chunksize_points,
|
|
119
|
-
)
|
|
124
|
+
):
|
|
125
|
+
# calculate farm results
|
|
126
|
+
farm_results = algo.calc_farm()
|
|
127
|
+
print("\nResults data:\n", farm_results)
|
|
120
128
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
129
|
+
if not args.nofig:
|
|
130
|
+
# xy horizontal flow plot
|
|
131
|
+
print("\nHorizontal flow figure output:")
|
|
132
|
+
o = foxes.output.FlowPlots2D(algo, farm_results)
|
|
133
|
+
g = o.gen_states_fig_xy(
|
|
134
|
+
args.var, resolution=10, xmin=-500, xmax=3000, rotor_color="red"
|
|
135
|
+
)
|
|
136
|
+
fig = next(g)
|
|
137
|
+
plt.show()
|
|
138
|
+
plt.close(fig)
|
|
124
139
|
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
140
|
+
# yz flow plot
|
|
141
|
+
print("\nVertical flow figure output:")
|
|
142
|
+
o = foxes.output.FlowPlots2D(algo, farm_results)
|
|
143
|
+
g = o.gen_states_fig_yz(
|
|
144
|
+
args.var,
|
|
145
|
+
resolution=5,
|
|
146
|
+
x=750,
|
|
147
|
+
ymin=-200,
|
|
148
|
+
ymax=200,
|
|
149
|
+
zmin=0,
|
|
150
|
+
zmax=250,
|
|
151
|
+
rotor_color="red",
|
|
152
|
+
verbosity=0,
|
|
153
|
+
)
|
|
154
|
+
fig = next(g)
|
|
155
|
+
plt.show()
|
|
156
|
+
plt.close(fig)
|
|
135
157
|
|
|
136
|
-
#
|
|
137
|
-
|
|
138
|
-
o
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
resolution=5,
|
|
142
|
-
x=750,
|
|
143
|
-
ymin=-200,
|
|
144
|
-
ymax=200,
|
|
145
|
-
zmin=0,
|
|
146
|
-
zmax=250,
|
|
147
|
-
rotor_color="red",
|
|
148
|
-
verbosity=0,
|
|
149
|
-
)
|
|
150
|
-
fig = next(g)
|
|
151
|
-
plt.show()
|
|
152
|
-
plt.close(fig)
|
|
158
|
+
# add capacity and efficiency to farm results
|
|
159
|
+
o = foxes.output.FarmResultsEval(farm_results)
|
|
160
|
+
o.add_capacity(algo)
|
|
161
|
+
o.add_capacity(algo, ambient=True)
|
|
162
|
+
o.add_efficiency()
|
|
153
163
|
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
FV.AMB_P,
|
|
172
|
-
FV.P,
|
|
173
|
-
FV.WD,
|
|
174
|
-
FV.YAW,
|
|
175
|
-
FV.YAWM,
|
|
164
|
+
# state-turbine results
|
|
165
|
+
farm_df = farm_results.to_dataframe()
|
|
166
|
+
print("\nFarm results data:\n")
|
|
167
|
+
print(
|
|
168
|
+
farm_df[
|
|
169
|
+
[
|
|
170
|
+
FV.X,
|
|
171
|
+
FV.AMB_REWS,
|
|
172
|
+
FV.REWS,
|
|
173
|
+
FV.AMB_TI,
|
|
174
|
+
FV.TI,
|
|
175
|
+
FV.AMB_P,
|
|
176
|
+
FV.P,
|
|
177
|
+
FV.WD,
|
|
178
|
+
FV.YAW,
|
|
179
|
+
FV.YAWM,
|
|
180
|
+
]
|
|
176
181
|
]
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
print()
|
|
182
|
+
)
|
|
183
|
+
print()
|
|
180
184
|
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
185
|
+
# results by turbine
|
|
186
|
+
turbine_results = o.reduce_states(
|
|
187
|
+
{
|
|
188
|
+
FV.AMB_P: "weights",
|
|
189
|
+
FV.P: "weights",
|
|
190
|
+
FV.AMB_CAP: "weights",
|
|
191
|
+
FV.CAP: "weights",
|
|
192
|
+
}
|
|
193
|
+
)
|
|
194
|
+
turbine_results[FV.AMB_YLD] = o.calc_turbine_yield(
|
|
195
|
+
algo=algo, annual=True, ambient=True
|
|
196
|
+
)
|
|
197
|
+
turbine_results[FV.YLD] = o.calc_turbine_yield(algo=algo, annual=True)
|
|
198
|
+
turbine_results[FV.EFF] = turbine_results[FV.P] / turbine_results[FV.AMB_P]
|
|
199
|
+
print("\nResults by turbine:\n")
|
|
200
|
+
print(turbine_results)
|
|
197
201
|
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
202
|
+
# power results
|
|
203
|
+
P0 = o.calc_mean_farm_power(ambient=True)
|
|
204
|
+
P = o.calc_mean_farm_power()
|
|
205
|
+
print(f"\nFarm power : {P / 1000:.1f} MW")
|
|
206
|
+
print(f"Farm ambient power: {P0 / 1000:.1f} MW")
|
|
207
|
+
print(f"Farm efficiency : {o.calc_farm_efficiency() * 100:.2f} %")
|
|
208
|
+
print(f"Annual farm yield : {turbine_results[FV.YLD].sum():.2f} GWh.")
|
|
@@ -477,7 +477,7 @@ class Downwind(Algorithm):
|
|
|
477
477
|
# 2) calculate ambient rotor results:
|
|
478
478
|
mlist.models.append(self.rotor_model)
|
|
479
479
|
calc_pars.append(calc_parameters.get(mlist.models[-1].name, {}))
|
|
480
|
-
calc_pars[-1]
|
|
480
|
+
calc_pars[-1]["store"] = True
|
|
481
481
|
|
|
482
482
|
# 3) run post-rotor turbine models via farm controller:
|
|
483
483
|
mlist.models.append(self.farm_controller)
|
|
@@ -508,7 +508,7 @@ class Downwind(Algorithm):
|
|
|
508
508
|
def _launch_parallel_farm_calc(
|
|
509
509
|
self,
|
|
510
510
|
mlist,
|
|
511
|
-
|
|
511
|
+
model_data,
|
|
512
512
|
outputs=None,
|
|
513
513
|
normalize=False,
|
|
514
514
|
**kwargs,
|
|
@@ -520,8 +520,8 @@ class Downwind(Algorithm):
|
|
|
520
520
|
----------
|
|
521
521
|
mlist: foxes.models.FarmDataModelList
|
|
522
522
|
The model list
|
|
523
|
-
|
|
524
|
-
The
|
|
523
|
+
model_data: xarray.Dataset
|
|
524
|
+
The initial model data
|
|
525
525
|
outputs: list of str, optional
|
|
526
526
|
The output variables, or None for defaults
|
|
527
527
|
normalize: bool
|
|
@@ -538,7 +538,7 @@ class Downwind(Algorithm):
|
|
|
538
538
|
"""
|
|
539
539
|
out_vars = self.farm_vars if outputs is None else outputs
|
|
540
540
|
farm_results = get_engine().run_calculation(
|
|
541
|
-
self, mlist,
|
|
541
|
+
self, mlist, model_data, out_vars=out_vars, **kwargs
|
|
542
542
|
)
|
|
543
543
|
|
|
544
544
|
if normalize:
|
|
@@ -74,17 +74,17 @@ class InitFarmData(FarmDataModel):
|
|
|
74
74
|
n_states = fdata.n_states
|
|
75
75
|
n_turbines = algo.n_turbines
|
|
76
76
|
|
|
77
|
-
#
|
|
78
|
-
fdata
|
|
79
|
-
|
|
77
|
+
# add and set X, Y, H, D:
|
|
78
|
+
fdata.add(
|
|
79
|
+
FV.TXYH,
|
|
80
|
+
np.zeros((n_states, n_turbines, 3), dtype=config.dtype_double),
|
|
81
|
+
(FC.STATE, FC.TURBINE, FC.XYH),
|
|
82
|
+
)
|
|
83
|
+
fdata.add(
|
|
84
|
+
FV.D,
|
|
85
|
+
np.zeros((n_states, n_turbines), dtype=config.dtype_double),
|
|
86
|
+
(FC.STATE, FC.TURBINE),
|
|
80
87
|
)
|
|
81
|
-
fdata.dims[FV.TXYH] = (FC.STATE, FC.TURBINE, FC.XYH)
|
|
82
|
-
for i, v in enumerate([FV.X, FV.Y, FV.H]):
|
|
83
|
-
fdata[v] = fdata[FV.TXYH][..., i]
|
|
84
|
-
fdata.dims[v] = (FC.STATE, FC.TURBINE)
|
|
85
|
-
|
|
86
|
-
# set X, Y, H, D:
|
|
87
|
-
fdata[FV.D] = np.zeros((n_states, n_turbines), dtype=config.dtype_double)
|
|
88
88
|
for ti, t in enumerate(algo.farm.turbines):
|
|
89
89
|
if len(t.xy.shape) == 1:
|
|
90
90
|
fdata[FV.TXYH][:, ti, :2] = t.xy[None, :]
|
|
@@ -103,34 +103,64 @@ class InitFarmData(FarmDataModel):
|
|
|
103
103
|
D = algo.farm_controller.turbine_types[ti].D
|
|
104
104
|
fdata[FV.D][:, ti] = D
|
|
105
105
|
|
|
106
|
-
# calc WD
|
|
106
|
+
# calc WD at rotor centres:
|
|
107
107
|
svrs = algo.states.output_point_vars(algo)
|
|
108
108
|
tdata = TData.from_points(points=fdata[FV.TXYH], variables=svrs)
|
|
109
109
|
sres = algo.states.calculate(algo, mdata, fdata, tdata)
|
|
110
|
-
fdata
|
|
110
|
+
fdata.add(
|
|
111
|
+
FV.WD,
|
|
112
|
+
sres[FV.WD][:, :, 0],
|
|
113
|
+
(FC.STATE, FC.TURBINE),
|
|
114
|
+
)
|
|
115
|
+
fdata.add(
|
|
116
|
+
FV.AMB_WD,
|
|
117
|
+
fdata[FV.WD].copy(),
|
|
118
|
+
(FC.STATE, FC.TURBINE),
|
|
119
|
+
)
|
|
111
120
|
del tdata, sres, svrs
|
|
112
121
|
|
|
113
|
-
# calculate
|
|
122
|
+
# calculate downwind order:
|
|
114
123
|
order = algo.wake_frame.calc_order(algo, mdata, fdata)
|
|
115
124
|
ssel = np.zeros_like(order)
|
|
116
125
|
ssel[:] = np.arange(n_states)[:, None]
|
|
117
|
-
fdata[FV.ORDER] = order
|
|
118
|
-
fdata[FV.ORDER_SSEL] = ssel
|
|
119
|
-
fdata[FV.ORDER_INV] = np.zeros_like(order)
|
|
120
|
-
fdata[FV.ORDER_INV][ssel, order] = np.arange(n_turbines)[None, :]
|
|
121
126
|
|
|
122
127
|
# apply downwind order to all data:
|
|
123
|
-
|
|
128
|
+
for data in [fdata, mdata]:
|
|
129
|
+
for k in data.keys():
|
|
130
|
+
if (
|
|
131
|
+
k not in [FV.X, FV.Y, FV.H]
|
|
132
|
+
and tuple(data.dims[k][:2]) == (FC.STATE, FC.TURBINE)
|
|
133
|
+
and np.any(data[k] != data[k][0, 0, None, None])
|
|
134
|
+
):
|
|
135
|
+
data[k][:] = data[k][ssel, order]
|
|
136
|
+
|
|
137
|
+
# add derived data:
|
|
124
138
|
for i, v in enumerate([FV.X, FV.Y, FV.H]):
|
|
125
|
-
fdata
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
)
|
|
134
|
-
|
|
139
|
+
fdata.add(
|
|
140
|
+
v,
|
|
141
|
+
fdata[FV.TXYH][:, :, i],
|
|
142
|
+
(FC.STATE, FC.TURBINE),
|
|
143
|
+
)
|
|
144
|
+
fdata.add(
|
|
145
|
+
FV.YAW,
|
|
146
|
+
fdata[FV.WD].copy(),
|
|
147
|
+
(FC.STATE, FC.TURBINE),
|
|
148
|
+
)
|
|
149
|
+
fdata.add(
|
|
150
|
+
FV.ORDER,
|
|
151
|
+
order,
|
|
152
|
+
(FC.STATE, FC.TURBINE),
|
|
153
|
+
)
|
|
154
|
+
fdata.add(
|
|
155
|
+
FV.ORDER_SSEL,
|
|
156
|
+
ssel,
|
|
157
|
+
(FC.STATE, FC.TURBINE),
|
|
158
|
+
)
|
|
159
|
+
fdata.add(
|
|
160
|
+
FV.ORDER_INV,
|
|
161
|
+
np.zeros_like(order),
|
|
162
|
+
(FC.STATE, FC.TURBINE),
|
|
163
|
+
)
|
|
164
|
+
fdata[FV.ORDER_INV][ssel, order] = np.arange(n_turbines)[None, :]
|
|
135
165
|
|
|
136
166
|
return {v: fdata[v] for v in self.output_farm_vars(algo)}
|
foxes/core/algorithm.py
CHANGED
|
@@ -63,8 +63,8 @@ class Algorithm(Model):
|
|
|
63
63
|
self.__farm = farm
|
|
64
64
|
self.__mbook = mbook
|
|
65
65
|
self.__dbook = StaticData() if dbook is None else dbook
|
|
66
|
-
self.__idata_mem = Dict(
|
|
67
|
-
self.__chunk_store = Dict(
|
|
66
|
+
self.__idata_mem = Dict(_name="idata_mem")
|
|
67
|
+
self.__chunk_store = Dict(_name="chunk_store")
|
|
68
68
|
|
|
69
69
|
if len(engine_pars):
|
|
70
70
|
if "engine_type" in engine_pars:
|
|
@@ -558,7 +558,7 @@ class Algorithm(Model):
|
|
|
558
558
|
"n_states": n_states,
|
|
559
559
|
"n_targets": n_targets,
|
|
560
560
|
},
|
|
561
|
-
|
|
561
|
+
_name=f"chunk_store_{i0}_{t0}",
|
|
562
562
|
)
|
|
563
563
|
|
|
564
564
|
self.chunk_store[key][name] = data.copy() if copy else data
|
|
@@ -638,11 +638,11 @@ class Algorithm(Model):
|
|
|
638
638
|
"""
|
|
639
639
|
chunk_store = self.chunk_store
|
|
640
640
|
if new_chunk_store is None:
|
|
641
|
-
self.__chunk_store = Dict(
|
|
641
|
+
self.__chunk_store = Dict(_name="chunk_store")
|
|
642
642
|
elif isinstance(new_chunk_store, Dict):
|
|
643
643
|
self.__chunk_store = new_chunk_store
|
|
644
644
|
else:
|
|
645
|
-
self.__chunk_store = Dict(
|
|
645
|
+
self.__chunk_store = Dict(_name="chunk_store")
|
|
646
646
|
self.__chunk_store.update(new_chunk_store)
|
|
647
647
|
return chunk_store
|
|
648
648
|
|
|
@@ -912,6 +912,7 @@ class Algorithm(Model):
|
|
|
912
912
|
isel=isel,
|
|
913
913
|
**kwargs,
|
|
914
914
|
)
|
|
915
|
+
self.reset_chunk_store(chunk_store)
|
|
915
916
|
|
|
916
917
|
# reset to not running:
|
|
917
918
|
self.unset_running(
|
foxes/core/data.py
CHANGED
|
@@ -53,7 +53,7 @@ class Data(Dict):
|
|
|
53
53
|
The data container name
|
|
54
54
|
|
|
55
55
|
"""
|
|
56
|
-
super().__init__(
|
|
56
|
+
super().__init__(_name=name)
|
|
57
57
|
|
|
58
58
|
self.update(data)
|
|
59
59
|
self.dims = dims
|
|
@@ -109,12 +109,12 @@ class Data(Dict):
|
|
|
109
109
|
or the corresponding index
|
|
110
110
|
|
|
111
111
|
"""
|
|
112
|
-
if
|
|
113
|
-
return None
|
|
114
|
-
elif counter:
|
|
112
|
+
if counter:
|
|
115
113
|
if self.__states_i0 is None:
|
|
116
114
|
raise KeyError(f"Data '{self.name}': states_i0 requested but not set")
|
|
117
115
|
return self.__states_i0
|
|
116
|
+
elif FC.STATE not in self:
|
|
117
|
+
return None
|
|
118
118
|
else:
|
|
119
119
|
return self[FC.STATE][0]
|
|
120
120
|
|
|
@@ -394,6 +394,74 @@ class FData(Data):
|
|
|
394
394
|
f"FData '{self.name}': Missing '{x}' in sizes, got {sorted(list(self.sizes.keys()))}"
|
|
395
395
|
)
|
|
396
396
|
|
|
397
|
+
@classmethod
|
|
398
|
+
def from_sizes(cls, n_states, n_turbines, *args, callback=None, **kwargs):
|
|
399
|
+
"""
|
|
400
|
+
Create Data object from model data
|
|
401
|
+
|
|
402
|
+
Parameters
|
|
403
|
+
----------
|
|
404
|
+
n_states: int
|
|
405
|
+
The number of states
|
|
406
|
+
n_turbines: int
|
|
407
|
+
The number of turbines
|
|
408
|
+
args: tuple, optional
|
|
409
|
+
Additional parameters for the constructor
|
|
410
|
+
callback: Function, optional
|
|
411
|
+
Function f(data, dims) that manipulates
|
|
412
|
+
the data and dims dicts before construction
|
|
413
|
+
kwargs: dict, optional
|
|
414
|
+
Additional parameters for the constructor
|
|
415
|
+
|
|
416
|
+
Returns
|
|
417
|
+
-------
|
|
418
|
+
data: Data
|
|
419
|
+
The data object
|
|
420
|
+
|
|
421
|
+
"""
|
|
422
|
+
data = cls(*args, **kwargs)
|
|
423
|
+
data.sizes[FC.STATE] = n_states
|
|
424
|
+
data.sizes[FC.TURBINE] = n_turbines
|
|
425
|
+
|
|
426
|
+
if callback is not None:
|
|
427
|
+
callback(data, data.dims)
|
|
428
|
+
|
|
429
|
+
return data
|
|
430
|
+
|
|
431
|
+
@classmethod
|
|
432
|
+
def from_mdata(cls, mdata, *args, callback=None, **kwargs):
|
|
433
|
+
"""
|
|
434
|
+
Create Data object from model data
|
|
435
|
+
|
|
436
|
+
Parameters
|
|
437
|
+
----------
|
|
438
|
+
mdata: MData
|
|
439
|
+
The model data
|
|
440
|
+
args: tuple, optional
|
|
441
|
+
Additional parameters for the constructor
|
|
442
|
+
callback: Function, optional
|
|
443
|
+
Function f(data, dims) that manipulates
|
|
444
|
+
the data and dims dicts before construction
|
|
445
|
+
kwargs: dict, optional
|
|
446
|
+
Additional parameters for the constructor
|
|
447
|
+
|
|
448
|
+
Returns
|
|
449
|
+
-------
|
|
450
|
+
data: Data
|
|
451
|
+
The data object
|
|
452
|
+
|
|
453
|
+
"""
|
|
454
|
+
data = cls(*args, **kwargs)
|
|
455
|
+
for v in [FC.STATE, FC.TURBINE]:
|
|
456
|
+
data[v] = mdata[v]
|
|
457
|
+
data.dims[v] = mdata.dims[v]
|
|
458
|
+
data.sizes[v] = mdata.sizes[v]
|
|
459
|
+
|
|
460
|
+
if callback is not None:
|
|
461
|
+
callback(data, data.dims)
|
|
462
|
+
|
|
463
|
+
return data
|
|
464
|
+
|
|
397
465
|
@classmethod
|
|
398
466
|
def from_dataset(cls, ds, *args, mdata=None, callback=None, **kwargs):
|
|
399
467
|
"""
|
|
@@ -427,6 +495,9 @@ class FData(Data):
|
|
|
427
495
|
if FC.STATE not in data:
|
|
428
496
|
data[FC.STATE] = mdata[FC.STATE]
|
|
429
497
|
dims[FC.STATE] = mdata.dims[FC.STATE]
|
|
498
|
+
if FC.TURBINE not in data:
|
|
499
|
+
data[FC.TURBINE] = mdata[FC.TURBINE]
|
|
500
|
+
dims[FC.TURBINE] = mdata.dims[FC.TURBINE]
|
|
430
501
|
if callback is not None:
|
|
431
502
|
callback(data, dims)
|
|
432
503
|
|
foxes/core/data_calc_model.py
CHANGED
|
@@ -45,8 +45,10 @@ class DataCalcModel(Model):
|
|
|
45
45
|
----------
|
|
46
46
|
algo: foxes.core.Algorithm
|
|
47
47
|
The calculation algorithm
|
|
48
|
-
data: tuple of foxes.core.Data
|
|
49
|
-
The input data
|
|
48
|
+
data: tuple of foxes.core.Data, optional
|
|
49
|
+
The input data, typically either (mdata, fdata) in
|
|
50
|
+
the case of farm calculations, or (mdata, fdata, tdata)
|
|
51
|
+
for point data calculations
|
|
50
52
|
parameters: dict, optional
|
|
51
53
|
The calculation parameters
|
|
52
54
|
|
foxes/core/engine.py
CHANGED
|
@@ -6,7 +6,6 @@ from xarray import Dataset
|
|
|
6
6
|
|
|
7
7
|
from .data import MData, FData, TData
|
|
8
8
|
from foxes.utils import new_instance
|
|
9
|
-
from foxes.config import config
|
|
10
9
|
import foxes.constants as FC
|
|
11
10
|
|
|
12
11
|
__global_engine_data__ = dict(
|
|
@@ -350,8 +349,9 @@ class Engine(ABC):
|
|
|
350
349
|
|
|
351
350
|
Returns
|
|
352
351
|
-------
|
|
353
|
-
data:
|
|
354
|
-
|
|
352
|
+
data: tuple of foxes.core.Data
|
|
353
|
+
The input data for the chunk calculation,
|
|
354
|
+
either (mdata, fdata) or (mdata, fdata, tdata)
|
|
355
355
|
|
|
356
356
|
"""
|
|
357
357
|
# prepare:
|
|
@@ -370,51 +370,37 @@ class Engine(ABC):
|
|
|
370
370
|
)
|
|
371
371
|
|
|
372
372
|
# create fdata:
|
|
373
|
-
if
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
373
|
+
if farm_data is not None:
|
|
374
|
+
fdata = FData.from_dataset(
|
|
375
|
+
farm_data,
|
|
376
|
+
mdata=mdata,
|
|
377
|
+
s_states=s_states,
|
|
378
|
+
callback=None,
|
|
379
|
+
states_i0=i0_states,
|
|
380
|
+
copy=True,
|
|
381
|
+
)
|
|
383
382
|
else:
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
s_states=s_states,
|
|
389
|
-
callback=cb,
|
|
390
|
-
states_i0=i0_states,
|
|
391
|
-
copy=True,
|
|
392
|
-
)
|
|
383
|
+
fdata = FData.from_mdata(
|
|
384
|
+
mdata=mdata,
|
|
385
|
+
states_i0=i0_states,
|
|
386
|
+
)
|
|
393
387
|
|
|
394
388
|
# create tdata:
|
|
395
|
-
tdata =
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
def cb(data, dims):
|
|
399
|
-
n_states = i1_states - i0_states
|
|
400
|
-
n_targets = i1_targets - i0_targets
|
|
401
|
-
for o in set(out_vars).difference(data.keys()):
|
|
402
|
-
data[o] = np.full(
|
|
403
|
-
(n_states, n_targets, 1), np.nan, dtype=config.dtype_double
|
|
404
|
-
)
|
|
405
|
-
dims[o] = (FC.STATE, FC.TARGET, FC.TPOINT)
|
|
406
|
-
|
|
407
|
-
tdata = TData.from_dataset(
|
|
389
|
+
tdata = (
|
|
390
|
+
TData.from_dataset(
|
|
408
391
|
point_data,
|
|
409
392
|
mdata=mdata,
|
|
410
393
|
s_states=s_states,
|
|
411
394
|
s_targets=s_targets,
|
|
412
|
-
callback=
|
|
395
|
+
callback=None,
|
|
413
396
|
states_i0=i0_states,
|
|
414
397
|
copy=True,
|
|
415
398
|
)
|
|
399
|
+
if point_data is not None
|
|
400
|
+
else None
|
|
401
|
+
)
|
|
416
402
|
|
|
417
|
-
return
|
|
403
|
+
return (mdata, fdata) if tdata is None else (mdata, fdata, tdata)
|
|
418
404
|
|
|
419
405
|
def combine_results(
|
|
420
406
|
self,
|
|
@@ -535,7 +521,14 @@ class Engine(ABC):
|
|
|
535
521
|
)
|
|
536
522
|
|
|
537
523
|
@abstractmethod
|
|
538
|
-
def run_calculation(
|
|
524
|
+
def run_calculation(
|
|
525
|
+
self,
|
|
526
|
+
algo,
|
|
527
|
+
model,
|
|
528
|
+
model_data=None,
|
|
529
|
+
farm_data=None,
|
|
530
|
+
point_data=None,
|
|
531
|
+
):
|
|
539
532
|
"""
|
|
540
533
|
Runs the model calculation
|
|
541
534
|
|
|
@@ -543,12 +536,12 @@ class Engine(ABC):
|
|
|
543
536
|
----------
|
|
544
537
|
algo: foxes.core.Algorithm
|
|
545
538
|
The algorithm object
|
|
546
|
-
model: foxes.core.DataCalcModel
|
|
539
|
+
model: foxes.core.DataCalcModel, optional
|
|
547
540
|
The model that whose calculate function
|
|
548
541
|
should be run
|
|
549
542
|
model_data: xarray.Dataset
|
|
550
543
|
The initial model data
|
|
551
|
-
farm_data: xarray.Dataset
|
|
544
|
+
farm_data: xarray.Dataset, optional
|
|
552
545
|
The initial farm data
|
|
553
546
|
point_data: xarray.Dataset, optional
|
|
554
547
|
The initial point data
|