foxes 1.3__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 +3 -3
- examples/abl_states/run.py +2 -2
- examples/compare_rotors_pwakes/run.py +1 -1
- examples/compare_wakes/run.py +1 -2
- examples/dyn_wakes/run.py +29 -6
- examples/field_data_nc/run.py +1 -1
- examples/induction/run.py +3 -3
- examples/multi_height/run.py +1 -1
- examples/power_mask/run.py +2 -2
- examples/quickstart/run.py +0 -1
- examples/random_timeseries/run.py +3 -4
- examples/scan_row/run.py +3 -3
- examples/sequential/run.py +33 -10
- examples/single_state/run.py +3 -4
- examples/states_lookup_table/run.py +3 -3
- examples/streamline_wakes/run.py +29 -6
- examples/tab_file/run.py +3 -3
- examples/timelines/run.py +29 -5
- examples/timeseries/run.py +3 -3
- examples/timeseries_slurm/run.py +3 -3
- examples/wind_rose/run.py +3 -3
- examples/yawed_wake/run.py +19 -9
- foxes/__init__.py +21 -17
- foxes/algorithms/__init__.py +6 -6
- foxes/algorithms/downwind/__init__.py +2 -2
- foxes/algorithms/downwind/downwind.py +49 -17
- foxes/algorithms/downwind/models/__init__.py +6 -6
- foxes/algorithms/downwind/models/farm_wakes_calc.py +11 -9
- foxes/algorithms/downwind/models/init_farm_data.py +58 -29
- foxes/algorithms/downwind/models/point_wakes_calc.py +7 -13
- foxes/algorithms/downwind/models/set_amb_farm_results.py +1 -1
- foxes/algorithms/downwind/models/set_amb_point_results.py +6 -6
- foxes/algorithms/iterative/__init__.py +7 -3
- foxes/algorithms/iterative/iterative.py +1 -2
- foxes/algorithms/iterative/models/__init__.py +7 -3
- foxes/algorithms/iterative/models/farm_wakes_calc.py +9 -5
- foxes/algorithms/sequential/__init__.py +3 -3
- foxes/algorithms/sequential/models/__init__.py +2 -2
- foxes/algorithms/sequential/sequential.py +3 -4
- foxes/config/__init__.py +5 -1
- foxes/constants.py +16 -0
- foxes/core/__init__.py +45 -22
- foxes/core/algorithm.py +5 -6
- foxes/core/data.py +94 -22
- foxes/core/data_calc_model.py +4 -2
- foxes/core/engine.py +42 -53
- foxes/core/farm_controller.py +2 -2
- foxes/core/farm_data_model.py +16 -13
- foxes/core/ground_model.py +4 -13
- foxes/core/model.py +24 -6
- foxes/core/partial_wakes_model.py +147 -10
- foxes/core/point_data_model.py +21 -17
- foxes/core/rotor_model.py +4 -3
- foxes/core/states.py +2 -3
- foxes/core/turbine.py +2 -1
- foxes/core/wake_deflection.py +130 -0
- foxes/core/wake_model.py +222 -9
- foxes/core/wake_superposition.py +122 -4
- foxes/core/wind_farm.py +6 -6
- foxes/data/__init__.py +7 -2
- 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/data/states/weibull_sectors_12.csv +13 -0
- foxes/data/states/weibull_sectors_12.nc +0 -0
- foxes/engines/__init__.py +14 -15
- foxes/engines/dask.py +42 -20
- foxes/engines/default.py +2 -2
- foxes/engines/numpy.py +11 -13
- foxes/engines/pool.py +20 -11
- foxes/engines/single.py +8 -6
- foxes/input/__init__.py +3 -3
- foxes/input/farm_layout/__init__.py +9 -8
- foxes/input/farm_layout/from_arrays.py +68 -0
- foxes/input/farm_layout/from_csv.py +1 -1
- foxes/input/farm_layout/ring.py +0 -1
- foxes/input/states/__init__.py +28 -12
- foxes/input/states/create/__init__.py +3 -2
- foxes/input/states/dataset_states.py +710 -0
- foxes/input/states/field_data.py +531 -0
- foxes/input/states/multi_height.py +11 -6
- foxes/input/states/one_point_flow.py +1 -4
- foxes/input/states/point_cloud_data.py +618 -0
- foxes/input/states/scan.py +2 -0
- foxes/input/states/single.py +3 -1
- foxes/input/states/states_table.py +23 -30
- foxes/input/states/weibull_sectors.py +330 -0
- foxes/input/states/wrg_states.py +8 -6
- foxes/input/yaml/__init__.py +9 -3
- foxes/input/yaml/dict.py +42 -41
- foxes/input/yaml/windio/__init__.py +10 -5
- foxes/input/yaml/windio/read_attributes.py +42 -29
- foxes/input/yaml/windio/read_farm.py +17 -15
- foxes/input/yaml/windio/read_fields.py +4 -2
- foxes/input/yaml/windio/read_outputs.py +25 -15
- foxes/input/yaml/windio/read_site.py +172 -11
- foxes/input/yaml/windio/windio.py +23 -11
- foxes/input/yaml/yaml.py +1 -0
- foxes/models/__init__.py +15 -14
- foxes/models/axial_induction/__init__.py +2 -2
- foxes/models/farm_controllers/__init__.py +1 -1
- foxes/models/farm_models/__init__.py +1 -1
- foxes/models/ground_models/__init__.py +3 -2
- foxes/models/ground_models/wake_mirror.py +3 -3
- foxes/models/model_book.py +190 -63
- foxes/models/partial_wakes/__init__.py +6 -6
- foxes/models/partial_wakes/axiwake.py +30 -5
- foxes/models/partial_wakes/centre.py +47 -0
- foxes/models/partial_wakes/rotor_points.py +41 -11
- foxes/models/partial_wakes/segregated.py +2 -25
- foxes/models/partial_wakes/top_hat.py +27 -2
- foxes/models/point_models/__init__.py +4 -4
- foxes/models/rotor_models/__init__.py +4 -3
- foxes/models/rotor_models/centre.py +1 -1
- foxes/models/rotor_models/direct_infusion.py +241 -0
- foxes/models/turbine_models/__init__.py +11 -11
- 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 -9
- 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 -6
- foxes/models/turbine_types/PCt_from_two.py +1 -2
- foxes/models/turbine_types/__init__.py +10 -9
- 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/models/vertical_profiles/__init__.py +7 -7
- foxes/models/wake_deflections/__init__.py +3 -0
- foxes/models/{wake_frames/yawed_wakes.py → wake_deflections/bastankhah2016.py} +32 -111
- foxes/models/wake_deflections/jimenez.py +277 -0
- foxes/models/wake_deflections/no_deflection.py +94 -0
- foxes/models/wake_frames/__init__.py +6 -7
- foxes/models/wake_frames/dynamic_wakes.py +12 -3
- foxes/models/wake_frames/rotor_wd.py +3 -1
- foxes/models/wake_frames/seq_dynamic_wakes.py +41 -7
- foxes/models/wake_frames/streamlines.py +8 -6
- foxes/models/wake_frames/timelines.py +9 -3
- foxes/models/wake_models/__init__.py +7 -7
- foxes/models/wake_models/dist_sliced.py +50 -84
- foxes/models/wake_models/gaussian.py +20 -0
- foxes/models/wake_models/induction/__init__.py +5 -5
- foxes/models/wake_models/induction/rankine_half_body.py +30 -71
- foxes/models/wake_models/induction/rathmann.py +65 -64
- foxes/models/wake_models/induction/self_similar.py +65 -68
- foxes/models/wake_models/induction/self_similar2020.py +0 -3
- foxes/models/wake_models/induction/vortex_sheet.py +71 -75
- foxes/models/wake_models/ti/__init__.py +2 -2
- foxes/models/wake_models/ti/crespo_hernandez.py +5 -3
- foxes/models/wake_models/ti/iec_ti.py +6 -4
- foxes/models/wake_models/top_hat.py +58 -7
- foxes/models/wake_models/wind/__init__.py +6 -4
- foxes/models/wake_models/wind/bastankhah14.py +25 -7
- foxes/models/wake_models/wind/bastankhah16.py +35 -3
- foxes/models/wake_models/wind/jensen.py +15 -2
- foxes/models/wake_models/wind/turbopark.py +28 -2
- foxes/models/wake_superpositions/__init__.py +18 -9
- foxes/models/wake_superpositions/ti_linear.py +4 -4
- foxes/models/wake_superpositions/ti_max.py +4 -4
- foxes/models/wake_superpositions/ti_pow.py +4 -4
- foxes/models/wake_superpositions/ti_quadratic.py +4 -4
- foxes/models/wake_superpositions/wind_vector.py +257 -0
- foxes/models/wake_superpositions/ws_linear.py +9 -10
- foxes/models/wake_superpositions/ws_max.py +8 -8
- foxes/models/wake_superpositions/ws_pow.py +8 -8
- foxes/models/wake_superpositions/ws_product.py +4 -4
- foxes/models/wake_superpositions/ws_quadratic.py +8 -8
- foxes/output/__init__.py +21 -19
- foxes/output/farm_layout.py +4 -2
- foxes/output/farm_results_eval.py +19 -16
- foxes/output/flow_plots_2d/__init__.py +2 -2
- foxes/output/flow_plots_2d/flow_plots.py +18 -0
- foxes/output/flow_plots_2d/get_fig.py +5 -2
- foxes/output/output.py +6 -1
- foxes/output/results_writer.py +1 -1
- foxes/output/rose_plot.py +13 -3
- foxes/output/rotor_point_plots.py +3 -0
- foxes/output/seq_plugins/__init__.py +2 -2
- foxes/output/seq_plugins/seq_flow_ani_plugin.py +0 -3
- foxes/output/seq_plugins/seq_wake_debug_plugin.py +0 -1
- foxes/output/state_turbine_map.py +3 -0
- foxes/output/turbine_type_curves.py +10 -8
- foxes/utils/__init__.py +37 -19
- foxes/utils/abl/__init__.py +4 -4
- foxes/utils/cubic_roots.py +1 -1
- foxes/utils/data_book.py +4 -3
- foxes/utils/dict.py +49 -37
- foxes/utils/exec_python.py +5 -5
- foxes/utils/factory.py +3 -5
- foxes/utils/geom2d/__init__.py +7 -5
- foxes/utils/geopandas_utils.py +2 -2
- foxes/utils/pandas_utils.py +4 -3
- foxes/utils/tab_files.py +0 -1
- foxes/utils/weibull.py +28 -0
- foxes/utils/wrg_utils.py +3 -1
- foxes/utils/xarray_utils.py +9 -2
- foxes/variables.py +67 -9
- {foxes-1.3.dist-info → foxes-1.5.dist-info}/METADATA +34 -63
- foxes-1.5.dist-info/RECORD +328 -0
- {foxes-1.3.dist-info → foxes-1.5.dist-info}/WHEEL +1 -1
- tests/1_verification/flappy_0_6/PCt_files/flappy/run.py +2 -3
- tests/1_verification/flappy_0_6/PCt_files/test_PCt_files.py +1 -1
- tests/1_verification/flappy_0_6/abl_states/flappy/run.py +0 -1
- tests/1_verification/flappy_0_6/partial_top_hat/flappy/run.py +0 -1
- tests/1_verification/flappy_0_6/partial_top_hat/test_partial_top_hat.py +0 -2
- tests/1_verification/flappy_0_6/row_Jensen_linear_centre/test_row_Jensen_linear_centre.py +0 -1
- tests/1_verification/flappy_0_6/row_Jensen_linear_tophat/test_row_Jensen_linear_tophat.py +0 -1
- tests/1_verification/flappy_0_6/row_Jensen_linear_tophat_IECTI2005/test_row_Jensen_linear_tophat_IECTI_2005.py +0 -1
- tests/1_verification/flappy_0_6/row_Jensen_linear_tophat_IECTI2019/test_row_Jensen_linear_tophat_IECTI_2019.py +0 -1
- tests/1_verification/flappy_0_6/row_Jensen_quadratic_centre/test_row_Jensen_quadratic_centre.py +0 -1
- tests/1_verification/flappy_0_6_2/grid_rotors/flappy/run.py +0 -2
- tests/1_verification/flappy_0_6_2/row_Bastankhah_Crespo/test_row_Bastankhah_Crespo.py +0 -1
- tests/1_verification/flappy_0_6_2/row_Bastankhah_linear_centre/flappy/run.py +0 -1
- tests/1_verification/flappy_0_6_2/row_Bastankhah_linear_centre/test_row_Bastankhah_linear_centre.py +0 -1
- foxes/input/states/field_data_nc.py +0 -847
- foxes/output/round.py +0 -10
- foxes/utils/pandas_helpers.py +0 -178
- foxes-1.3.dist-info/RECORD +0 -313
- {foxes-1.3.dist-info → foxes-1.5.dist-info}/entry_points.txt +0 -0
- {foxes-1.3.dist-info → foxes-1.5.dist-info/licenses}/LICENSE +0 -0
- {foxes-1.3.dist-info → foxes-1.5.dist-info}/top_level.txt +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import numpy as np
|
|
2
2
|
from copy import deepcopy
|
|
3
3
|
|
|
4
|
-
from foxes.core import FarmDataModel
|
|
4
|
+
from foxes.core import FarmDataModel
|
|
5
5
|
import foxes.constants as FC
|
|
6
6
|
import foxes.variables as FV
|
|
7
7
|
|
|
@@ -99,8 +99,14 @@ class FarmWakesCalculation(FarmDataModel):
|
|
|
99
99
|
for wname, wmodel in algo.wake_models.items():
|
|
100
100
|
pwake = algo.partial_wakes[wname]
|
|
101
101
|
if pwake.name not in pwake2tdata:
|
|
102
|
-
|
|
103
|
-
|
|
102
|
+
wmodels = [
|
|
103
|
+
wm
|
|
104
|
+
for wn, wm in algo.wake_models.items()
|
|
105
|
+
if algo.partial_wakes[wn] is pwake
|
|
106
|
+
]
|
|
107
|
+
pwake2tdata[pwake.name] = pwake.get_initial_tdata(
|
|
108
|
+
algo, mdata, fdata, amb_res, rwghts, wmodels
|
|
109
|
+
)
|
|
104
110
|
|
|
105
111
|
def _get_wdata(tdatap, wdeltas, variables, s):
|
|
106
112
|
"""Helper function for wake data extraction"""
|
|
@@ -117,7 +123,6 @@ class FarmWakesCalculation(FarmDataModel):
|
|
|
117
123
|
wdeltas = pwake.new_wake_deltas(algo, mdata, fdata, tdatap, wmodel)
|
|
118
124
|
|
|
119
125
|
for oi in range(n_turbines):
|
|
120
|
-
|
|
121
126
|
if oi > 0:
|
|
122
127
|
tdata, wdelta = _get_wdata(
|
|
123
128
|
tdatap, wdeltas, [FC.STATE, FC.TARGET], np.s_[:, :oi]
|
|
@@ -140,7 +145,6 @@ class FarmWakesCalculation(FarmDataModel):
|
|
|
140
145
|
mdata,
|
|
141
146
|
fdata,
|
|
142
147
|
tdatap,
|
|
143
|
-
amb_res,
|
|
144
148
|
rwghts,
|
|
145
149
|
wdeltas,
|
|
146
150
|
wmodel,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
from .sequential import Sequential
|
|
2
|
-
from .models import SequentialPlugin
|
|
1
|
+
from .sequential import Sequential as Sequential
|
|
2
|
+
from .models import SequentialPlugin as SequentialPlugin
|
|
3
3
|
|
|
4
|
-
from . import models
|
|
4
|
+
from . import models as models
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
from .plugin import SequentialPlugin
|
|
2
|
-
from .seq_state import SeqState
|
|
1
|
+
from .plugin import SequentialPlugin as SequentialPlugin
|
|
2
|
+
from .seq_state import SeqState as SeqState
|
|
@@ -154,7 +154,7 @@ class Sequential(Iterative):
|
|
|
154
154
|
if self._verbo0 > 0:
|
|
155
155
|
print("\nInput data:\n")
|
|
156
156
|
print(self._model_data)
|
|
157
|
-
print(
|
|
157
|
+
print("\nOutput farm variables:", ", ".join(self.farm_vars))
|
|
158
158
|
print()
|
|
159
159
|
|
|
160
160
|
sts = self._model_data[FC.STATE].to_numpy()
|
|
@@ -188,7 +188,6 @@ class Sequential(Iterative):
|
|
|
188
188
|
"""Run calculation for current step, then iterate to next"""
|
|
189
189
|
|
|
190
190
|
if self._i < len(self._inds):
|
|
191
|
-
|
|
192
191
|
self._counter = self._i
|
|
193
192
|
self.states._counter = self._i
|
|
194
193
|
self.states._size = 1
|
|
@@ -401,7 +400,7 @@ class Sequential(Iterative):
|
|
|
401
400
|
|
|
402
401
|
"""
|
|
403
402
|
if not self.iterating:
|
|
404
|
-
raise ValueError(
|
|
403
|
+
raise ValueError("calc_farm call is only allowed during iterations")
|
|
405
404
|
return self.cur_farm_results
|
|
406
405
|
|
|
407
406
|
def calc_points(
|
|
@@ -433,6 +432,6 @@ class Sequential(Iterative):
|
|
|
433
432
|
|
|
434
433
|
"""
|
|
435
434
|
if not self.iterating:
|
|
436
|
-
raise ValueError(
|
|
435
|
+
raise ValueError("calc_points call is only allowed during iterations")
|
|
437
436
|
|
|
438
437
|
return super().calc_points(farm_results, points, finalize=False, **kwargs)
|
foxes/config/__init__.py
CHANGED
|
@@ -1 +1,5 @@
|
|
|
1
|
-
from .config import Config
|
|
1
|
+
from .config import Config as Config
|
|
2
|
+
from .config import config as config
|
|
3
|
+
from .config import get_path as get_path
|
|
4
|
+
from .config import get_input_path as get_input_path
|
|
5
|
+
from .config import get_output_path as get_output_path
|
foxes/constants.py
CHANGED
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
XY = "xy"
|
|
2
|
+
""" The vector (x, y)
|
|
3
|
+
:group: foxes.variables
|
|
4
|
+
"""
|
|
5
|
+
|
|
1
6
|
XYH = "xyh"
|
|
2
7
|
""" The vector (x, y, height)
|
|
3
8
|
:group: foxes.variables
|
|
@@ -146,6 +151,17 @@ BLOCK_CONVERGENCE = "block_convergence"
|
|
|
146
151
|
"""
|
|
147
152
|
|
|
148
153
|
|
|
154
|
+
WDEFL_ROT_ANGLE = "wake_deflection_rotation_angle"
|
|
155
|
+
"""Identifier for the wake deflection rotation angle data
|
|
156
|
+
:group: foxes.constants
|
|
157
|
+
"""
|
|
158
|
+
|
|
159
|
+
WDEFL_DWS_FACTOR = "wake_deflection_deltaws_factor"
|
|
160
|
+
"""Identifier for the wake deflection delta wind speed factor data
|
|
161
|
+
:group: foxes.constants
|
|
162
|
+
"""
|
|
163
|
+
|
|
164
|
+
|
|
149
165
|
KAPPA = 0.41
|
|
150
166
|
""" The Von Karman constant
|
|
151
167
|
:group: foxes.constants
|
foxes/core/__init__.py
CHANGED
|
@@ -2,25 +2,48 @@
|
|
|
2
2
|
Abstract classes and core functionality.
|
|
3
3
|
"""
|
|
4
4
|
|
|
5
|
-
from .
|
|
6
|
-
from .
|
|
7
|
-
from .
|
|
8
|
-
from .
|
|
9
|
-
from .
|
|
10
|
-
from .
|
|
11
|
-
from .
|
|
12
|
-
from .
|
|
13
|
-
from .
|
|
14
|
-
from .
|
|
15
|
-
from .
|
|
16
|
-
from .
|
|
17
|
-
from .
|
|
18
|
-
from .
|
|
19
|
-
from .
|
|
20
|
-
from .
|
|
21
|
-
|
|
22
|
-
from .
|
|
23
|
-
from .
|
|
24
|
-
from .
|
|
25
|
-
from .
|
|
26
|
-
|
|
5
|
+
from .model import Model as Model
|
|
6
|
+
from .data_calc_model import DataCalcModel as DataCalcModel
|
|
7
|
+
from .wind_farm import WindFarm as WindFarm
|
|
8
|
+
from .algorithm import Algorithm as Algorithm
|
|
9
|
+
from .rotor_model import RotorModel as RotorModel
|
|
10
|
+
from .farm_model import FarmModel as FarmModel
|
|
11
|
+
from .turbine_model import TurbineModel as TurbineModel
|
|
12
|
+
from .turbine_type import TurbineType as TurbineType
|
|
13
|
+
from .farm_controller import FarmController as FarmController
|
|
14
|
+
from .turbine import Turbine as Turbine
|
|
15
|
+
from .partial_wakes_model import PartialWakesModel as PartialWakesModel
|
|
16
|
+
from .wake_frame import WakeFrame as WakeFrame
|
|
17
|
+
from .wake_deflection import WakeDeflection as WakeDeflection
|
|
18
|
+
from .vertical_profile import VerticalProfile as VerticalProfile
|
|
19
|
+
from .axial_induction_model import AxialInductionModel as AxialInductionModel
|
|
20
|
+
from .ground_model import GroundModel as GroundModel
|
|
21
|
+
|
|
22
|
+
from .data import Data as Data
|
|
23
|
+
from .data import MData as MData
|
|
24
|
+
from .data import FData as FData
|
|
25
|
+
from .data import TData as TData
|
|
26
|
+
|
|
27
|
+
from .engine import Engine as Engine
|
|
28
|
+
from .engine import get_engine as get_engine
|
|
29
|
+
from .engine import has_engine as has_engine
|
|
30
|
+
from .engine import reset_engine as reset_engine
|
|
31
|
+
|
|
32
|
+
from .states import States as States
|
|
33
|
+
from .states import ExtendedStates as ExtendedStates
|
|
34
|
+
|
|
35
|
+
from .farm_data_model import FarmDataModel as FarmDataModel
|
|
36
|
+
from .farm_data_model import FarmDataModelList as FarmDataModelList
|
|
37
|
+
|
|
38
|
+
from .point_data_model import PointDataModel as PointDataModel
|
|
39
|
+
from .point_data_model import PointDataModelList as PointDataModelList
|
|
40
|
+
|
|
41
|
+
from .wake_model import WakeModel as WakeModel
|
|
42
|
+
from .wake_model import SingleTurbineWakeModel as SingleTurbineWakeModel
|
|
43
|
+
from .wake_model import TurbineInductionModel as TurbineInductionModel
|
|
44
|
+
from .wake_model import WakeK as WakeK
|
|
45
|
+
|
|
46
|
+
from .wake_superposition import WakeSuperposition as WakeSuperposition
|
|
47
|
+
from .wake_superposition import (
|
|
48
|
+
WindVectorWakeSuperposition as WindVectorWakeSuperposition,
|
|
49
|
+
)
|
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:
|
|
@@ -472,7 +472,6 @@ class Algorithm(Model):
|
|
|
472
472
|
n_targets = int(tdata.n_targets if tdata is not None else 0)
|
|
473
473
|
|
|
474
474
|
if prev_s > 0 or prev_t > 0:
|
|
475
|
-
|
|
476
475
|
inds = np.array(
|
|
477
476
|
[
|
|
478
477
|
[
|
|
@@ -559,7 +558,7 @@ class Algorithm(Model):
|
|
|
559
558
|
"n_states": n_states,
|
|
560
559
|
"n_targets": n_targets,
|
|
561
560
|
},
|
|
562
|
-
|
|
561
|
+
_name=f"chunk_store_{i0}_{t0}",
|
|
563
562
|
)
|
|
564
563
|
|
|
565
564
|
self.chunk_store[key][name] = data.copy() if copy else data
|
|
@@ -639,11 +638,11 @@ class Algorithm(Model):
|
|
|
639
638
|
"""
|
|
640
639
|
chunk_store = self.chunk_store
|
|
641
640
|
if new_chunk_store is None:
|
|
642
|
-
self.__chunk_store = Dict(
|
|
641
|
+
self.__chunk_store = Dict(_name="chunk_store")
|
|
643
642
|
elif isinstance(new_chunk_store, Dict):
|
|
644
643
|
self.__chunk_store = new_chunk_store
|
|
645
644
|
else:
|
|
646
|
-
self.__chunk_store = Dict(
|
|
645
|
+
self.__chunk_store = Dict(_name="chunk_store")
|
|
647
646
|
self.__chunk_store.update(new_chunk_store)
|
|
648
647
|
return chunk_store
|
|
649
648
|
|
foxes/core/data.py
CHANGED
|
@@ -28,9 +28,9 @@ class Data(Dict):
|
|
|
28
28
|
|
|
29
29
|
def __init__(
|
|
30
30
|
self,
|
|
31
|
-
data,
|
|
32
|
-
dims,
|
|
33
|
-
loop_dims,
|
|
31
|
+
data={},
|
|
32
|
+
dims={},
|
|
33
|
+
loop_dims=[FC.STATE],
|
|
34
34
|
states_i0=None,
|
|
35
35
|
name="data",
|
|
36
36
|
):
|
|
@@ -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
|
|
|
@@ -153,13 +153,13 @@ class Data(Dict):
|
|
|
153
153
|
# remove axes of size 1, added by dask for extra loop dimensions:
|
|
154
154
|
if dims is not None:
|
|
155
155
|
if len(dims) != len(data.shape):
|
|
156
|
-
for li,
|
|
157
|
-
if data.shape[li] == 1 and (len(dims) < li + 1 or dims[li] !=
|
|
156
|
+
for li, ld in enumerate(self.loop_dims):
|
|
157
|
+
if data.shape[li] == 1 and (len(dims) < li + 1 or dims[li] != ld):
|
|
158
158
|
self[name] = np.squeeze(data, axis=li)
|
|
159
159
|
for ci, c in enumerate(dims):
|
|
160
160
|
if c not in self.sizes or self.sizes[c] == 1:
|
|
161
161
|
self.sizes[c] = self[name].shape[ci]
|
|
162
|
-
elif self[name].shape[ci] == 1:
|
|
162
|
+
elif c != FC.TARGET and self[name].shape[ci] == 1:
|
|
163
163
|
pass
|
|
164
164
|
elif self.sizes[c] != self[name].shape[ci]:
|
|
165
165
|
raise ValueError(
|
|
@@ -240,9 +240,14 @@ class Data(Dict):
|
|
|
240
240
|
)
|
|
241
241
|
else:
|
|
242
242
|
states_i0 = None
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
)
|
|
243
|
+
|
|
244
|
+
cls = type(self)
|
|
245
|
+
if issubclass(cls, Data):
|
|
246
|
+
return cls(data, dims, name=name, states_i0=states_i0)
|
|
247
|
+
else:
|
|
248
|
+
return cls(
|
|
249
|
+
data, dims, loop_dims=self.loop_dims, name=name, states_i0=states_i0
|
|
250
|
+
)
|
|
246
251
|
|
|
247
252
|
@classmethod
|
|
248
253
|
def from_dataset(cls, ds, *args, callback=None, s_states=None, copy=True, **kwargs):
|
|
@@ -360,7 +365,7 @@ class FData(Data):
|
|
|
360
365
|
Arguments for the base class
|
|
361
366
|
|
|
362
367
|
"""
|
|
363
|
-
super().__init__(*args, name=name, **kwargs)
|
|
368
|
+
super().__init__(*args, loop_dims=[FC.STATE], name=name, **kwargs)
|
|
364
369
|
|
|
365
370
|
def _run_entry_checks(self, name, data, dims):
|
|
366
371
|
"""Run entry checks on new data"""
|
|
@@ -389,6 +394,74 @@ class FData(Data):
|
|
|
389
394
|
f"FData '{self.name}': Missing '{x}' in sizes, got {sorted(list(self.sizes.keys()))}"
|
|
390
395
|
)
|
|
391
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
|
+
|
|
392
465
|
@classmethod
|
|
393
466
|
def from_dataset(cls, ds, *args, mdata=None, callback=None, **kwargs):
|
|
394
467
|
"""
|
|
@@ -422,6 +495,9 @@ class FData(Data):
|
|
|
422
495
|
if FC.STATE not in data:
|
|
423
496
|
data[FC.STATE] = mdata[FC.STATE]
|
|
424
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]
|
|
425
501
|
if callback is not None:
|
|
426
502
|
callback(data, dims)
|
|
427
503
|
|
|
@@ -453,7 +529,7 @@ class TData(Data):
|
|
|
453
529
|
Arguments for the base class
|
|
454
530
|
|
|
455
531
|
"""
|
|
456
|
-
super().__init__(*args, name=name, **kwargs)
|
|
532
|
+
super().__init__(*args, loop_dims=[FC.STATE, FC.TARGET], name=name, **kwargs)
|
|
457
533
|
|
|
458
534
|
def _run_entry_checks(self, name, data, dims):
|
|
459
535
|
"""Run entry checks on new data"""
|
|
@@ -635,9 +711,7 @@ class TData(Data):
|
|
|
635
711
|
for v in variables:
|
|
636
712
|
data[v] = np.full_like(points[:, :, None, 0], np.nan)
|
|
637
713
|
dims[v] = (FC.STATE, FC.TARGET, FC.TPOINT)
|
|
638
|
-
return cls(
|
|
639
|
-
data=data, dims=dims, loop_dims=[FC.STATE, FC.TARGET], name=name, **kwargs
|
|
640
|
-
)
|
|
714
|
+
return cls(data=data, dims=dims, name=name, **kwargs)
|
|
641
715
|
|
|
642
716
|
@classmethod
|
|
643
717
|
def from_tpoints(
|
|
@@ -694,9 +768,7 @@ class TData(Data):
|
|
|
694
768
|
for v in variables:
|
|
695
769
|
data[v] = np.full_like(tpoints[..., 0], np.nan)
|
|
696
770
|
dims[v] = (FC.STATE, FC.TARGET, FC.TPOINT)
|
|
697
|
-
return cls(
|
|
698
|
-
data=data, dims=dims, loop_dims=[FC.STATE, FC.TARGET], name=name, **kwargs
|
|
699
|
-
)
|
|
771
|
+
return cls(data=data, dims=dims, name=name, **kwargs)
|
|
700
772
|
|
|
701
773
|
@classmethod
|
|
702
774
|
def from_dataset(
|
|
@@ -764,7 +836,7 @@ class TData(Data):
|
|
|
764
836
|
FC.TPOINT,
|
|
765
837
|
):
|
|
766
838
|
raise ValueError(
|
|
767
|
-
f"Expecting coordinates '{
|
|
839
|
+
f"Expecting coordinates '{(FC.STATE, FC.TARGET, FC.TPOINT)}' at positions 0-2 for data variable '{v}', got {dims[v]}"
|
|
768
840
|
)
|
|
769
841
|
else:
|
|
770
842
|
data[v] = d[:, s_targets]
|
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
|
@@ -4,9 +4,8 @@ from abc import ABC, abstractmethod
|
|
|
4
4
|
from tqdm import tqdm
|
|
5
5
|
from xarray import Dataset
|
|
6
6
|
|
|
7
|
-
from
|
|
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(
|
|
@@ -73,7 +72,7 @@ class Engine(ABC):
|
|
|
73
72
|
|
|
74
73
|
def __enter__(self):
|
|
75
74
|
if self.__entered:
|
|
76
|
-
raise ValueError(
|
|
75
|
+
raise ValueError("Enter called for already entered engine")
|
|
77
76
|
self.__entered = True
|
|
78
77
|
if not self.initialized:
|
|
79
78
|
self.initialize()
|
|
@@ -81,7 +80,7 @@ class Engine(ABC):
|
|
|
81
80
|
|
|
82
81
|
def __exit__(self, *exit_args):
|
|
83
82
|
if not self.__entered:
|
|
84
|
-
raise ValueError(
|
|
83
|
+
raise ValueError("Exit called for not entered engine")
|
|
85
84
|
self.__entered = False
|
|
86
85
|
if self.initialized:
|
|
87
86
|
self.finalize(*exit_args)
|
|
@@ -127,7 +126,6 @@ class Engine(ABC):
|
|
|
127
126
|
raise ValueError(
|
|
128
127
|
f"Cannot initialize engine '{type(self).__name__}', since engine already set to '{type(get_engine()).__name__}'"
|
|
129
128
|
)
|
|
130
|
-
global __global_engine_data__
|
|
131
129
|
__global_engine_data__["engine"] = self
|
|
132
130
|
self.__initialized = True
|
|
133
131
|
|
|
@@ -148,7 +146,6 @@ class Engine(ABC):
|
|
|
148
146
|
if self.entered:
|
|
149
147
|
self.__exit__(type, value, traceback)
|
|
150
148
|
elif self.initialized:
|
|
151
|
-
global __global_engine_data__
|
|
152
149
|
__global_engine_data__["engine"] = None
|
|
153
150
|
self.__initialized = False
|
|
154
151
|
|
|
@@ -304,9 +301,9 @@ class Engine(ABC):
|
|
|
304
301
|
chunk_sizes_targets[-extra:] += 1
|
|
305
302
|
|
|
306
303
|
s = np.sum(chunk_sizes_targets)
|
|
307
|
-
assert (
|
|
308
|
-
s
|
|
309
|
-
)
|
|
304
|
+
assert s == n_targets, (
|
|
305
|
+
f"Targets count mismatch: Expecting {n_targets}, chunks sum is {s}. Chunks: {[int(c) for c in chunk_sizes_targets]}"
|
|
306
|
+
)
|
|
310
307
|
|
|
311
308
|
chunk_sizes_states = np.full(n_chunks_states, chunk_size_states)
|
|
312
309
|
extra = n_states - n_chunks_states * chunk_size_states
|
|
@@ -314,9 +311,9 @@ class Engine(ABC):
|
|
|
314
311
|
chunk_sizes_states[-extra:] += 1
|
|
315
312
|
|
|
316
313
|
s = np.sum(chunk_sizes_states)
|
|
317
|
-
assert (
|
|
318
|
-
s
|
|
319
|
-
)
|
|
314
|
+
assert s == n_states, (
|
|
315
|
+
f"States count mismatch: Expecting {n_states}, chunks sum is {s}. Chunks: {[int(c) for c in chunk_sizes_states]}"
|
|
316
|
+
)
|
|
320
317
|
|
|
321
318
|
return chunk_sizes_states, chunk_sizes_targets
|
|
322
319
|
|
|
@@ -352,8 +349,9 @@ class Engine(ABC):
|
|
|
352
349
|
|
|
353
350
|
Returns
|
|
354
351
|
-------
|
|
355
|
-
data:
|
|
356
|
-
|
|
352
|
+
data: tuple of foxes.core.Data
|
|
353
|
+
The input data for the chunk calculation,
|
|
354
|
+
either (mdata, fdata) or (mdata, fdata, tdata)
|
|
357
355
|
|
|
358
356
|
"""
|
|
359
357
|
# prepare:
|
|
@@ -372,53 +370,37 @@ class Engine(ABC):
|
|
|
372
370
|
)
|
|
373
371
|
|
|
374
372
|
# create fdata:
|
|
375
|
-
if
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
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
|
+
)
|
|
385
382
|
else:
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
s_states=s_states,
|
|
391
|
-
callback=cb,
|
|
392
|
-
loop_dims=[FC.STATE],
|
|
393
|
-
states_i0=i0_states,
|
|
394
|
-
copy=True,
|
|
395
|
-
)
|
|
383
|
+
fdata = FData.from_mdata(
|
|
384
|
+
mdata=mdata,
|
|
385
|
+
states_i0=i0_states,
|
|
386
|
+
)
|
|
396
387
|
|
|
397
388
|
# create tdata:
|
|
398
|
-
tdata =
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
def cb(data, dims):
|
|
402
|
-
n_states = i1_states - i0_states
|
|
403
|
-
n_targets = i1_targets - i0_targets
|
|
404
|
-
for o in set(out_vars).difference(data.keys()):
|
|
405
|
-
data[o] = np.full(
|
|
406
|
-
(n_states, n_targets, 1), np.nan, dtype=config.dtype_double
|
|
407
|
-
)
|
|
408
|
-
dims[o] = (FC.STATE, FC.TARGET, FC.TPOINT)
|
|
409
|
-
|
|
410
|
-
tdata = TData.from_dataset(
|
|
389
|
+
tdata = (
|
|
390
|
+
TData.from_dataset(
|
|
411
391
|
point_data,
|
|
412
392
|
mdata=mdata,
|
|
413
393
|
s_states=s_states,
|
|
414
394
|
s_targets=s_targets,
|
|
415
|
-
callback=
|
|
416
|
-
loop_dims=[FC.STATE, FC.TARGET],
|
|
395
|
+
callback=None,
|
|
417
396
|
states_i0=i0_states,
|
|
418
397
|
copy=True,
|
|
419
398
|
)
|
|
399
|
+
if point_data is not None
|
|
400
|
+
else None
|
|
401
|
+
)
|
|
420
402
|
|
|
421
|
-
return
|
|
403
|
+
return (mdata, fdata) if tdata is None else (mdata, fdata, tdata)
|
|
422
404
|
|
|
423
405
|
def combine_results(
|
|
424
406
|
self,
|
|
@@ -539,7 +521,14 @@ class Engine(ABC):
|
|
|
539
521
|
)
|
|
540
522
|
|
|
541
523
|
@abstractmethod
|
|
542
|
-
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
|
+
):
|
|
543
532
|
"""
|
|
544
533
|
Runs the model calculation
|
|
545
534
|
|
|
@@ -547,12 +536,12 @@ class Engine(ABC):
|
|
|
547
536
|
----------
|
|
548
537
|
algo: foxes.core.Algorithm
|
|
549
538
|
The algorithm object
|
|
550
|
-
model: foxes.core.DataCalcModel
|
|
539
|
+
model: foxes.core.DataCalcModel, optional
|
|
551
540
|
The model that whose calculate function
|
|
552
541
|
should be run
|
|
553
542
|
model_data: xarray.Dataset
|
|
554
543
|
The initial model data
|
|
555
|
-
farm_data: xarray.Dataset
|
|
544
|
+
farm_data: xarray.Dataset, optional
|
|
556
545
|
The initial farm data
|
|
557
546
|
point_data: xarray.Dataset, optional
|
|
558
547
|
The initial point data
|
foxes/core/farm_controller.py
CHANGED
|
@@ -171,7 +171,7 @@ class FarmController(FarmDataModel):
|
|
|
171
171
|
for ti, t in enumerate(algo.farm.turbines):
|
|
172
172
|
if tmis[ti] != len(models[ti]):
|
|
173
173
|
raise ValueError(
|
|
174
|
-
f"Turbine {ti}, {t.name}: Could not find turbine model order that includes all {mtype} turbine models, missing {t.models[tmis[ti]:]}"
|
|
174
|
+
f"Turbine {ti}, {t.name}: Could not find turbine model order that includes all {mtype} turbine models, missing {t.models[tmis[ti] :]}"
|
|
175
175
|
)
|
|
176
176
|
|
|
177
177
|
return [m.name for m in tmodels], tmsels
|
|
@@ -253,7 +253,7 @@ class FarmController(FarmDataModel):
|
|
|
253
253
|
prer = m.pre_rotor
|
|
254
254
|
elif not prer and m.pre_rotor:
|
|
255
255
|
raise ValueError(
|
|
256
|
-
f"Turbine {ti}, {t.name}: Model is classified as pre-rotor, but following the post-rotor model '{t.models[mi-1]}'"
|
|
256
|
+
f"Turbine {ti}, {t.name}: Model is classified as pre-rotor, but following the post-rotor model '{t.models[mi - 1]}'"
|
|
257
257
|
)
|
|
258
258
|
if m.pre_rotor:
|
|
259
259
|
prer_models[ti].append(m)
|