foxes 1.2.5__py3-none-any.whl → 1.4__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/induction/run.py +3 -3
- examples/multi_height/run.py +1 -1
- examples/power_mask/run.py +2 -2
- examples/quickstart/run.py +16 -0
- 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 +27 -4
- 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 +16 -8
- foxes/__init__.py +22 -18
- foxes/algorithms/__init__.py +6 -6
- foxes/algorithms/downwind/__init__.py +2 -2
- foxes/algorithms/downwind/downwind.py +53 -27
- foxes/algorithms/downwind/models/__init__.py +6 -6
- foxes/algorithms/downwind/models/farm_wakes_calc.py +22 -14
- foxes/algorithms/downwind/models/init_farm_data.py +4 -5
- foxes/algorithms/downwind/models/point_wakes_calc.py +7 -13
- foxes/algorithms/downwind/models/reorder_farm_output.py +5 -1
- foxes/algorithms/downwind/models/set_amb_point_results.py +7 -7
- 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 +15 -8
- foxes/algorithms/sequential/__init__.py +3 -3
- foxes/algorithms/sequential/models/__init__.py +2 -2
- foxes/algorithms/sequential/models/seq_state.py +0 -18
- foxes/algorithms/sequential/sequential.py +8 -22
- foxes/config/__init__.py +5 -1
- foxes/constants.py +22 -0
- foxes/core/__init__.py +45 -22
- foxes/core/algorithm.py +0 -1
- foxes/core/data.py +56 -29
- foxes/core/engine.py +28 -14
- foxes/core/farm_controller.py +2 -2
- foxes/core/farm_data_model.py +1 -0
- foxes/core/ground_model.py +4 -13
- foxes/core/model.py +5 -5
- foxes/core/partial_wakes_model.py +147 -10
- foxes/core/point_data_model.py +2 -3
- foxes/core/rotor_model.py +42 -38
- foxes/core/states.py +4 -50
- 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/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 +39 -14
- foxes/engines/numpy.py +0 -3
- foxes/input/__init__.py +3 -3
- foxes/input/farm_layout/__init__.py +8 -8
- foxes/input/farm_layout/from_csv.py +1 -1
- foxes/input/farm_layout/ring.py +0 -1
- foxes/input/states/__init__.py +22 -11
- foxes/input/states/create/__init__.py +3 -2
- foxes/input/states/field_data_nc.py +48 -84
- foxes/input/states/multi_height.py +40 -60
- foxes/input/states/one_point_flow.py +22 -25
- foxes/input/states/scan.py +6 -19
- foxes/input/states/single.py +6 -18
- foxes/input/states/states_table.py +25 -44
- foxes/input/states/weibull_sectors.py +225 -0
- foxes/input/states/wrg_states.py +151 -37
- foxes/input/yaml/__init__.py +9 -3
- foxes/input/yaml/dict.py +19 -19
- foxes/input/yaml/windio/__init__.py +10 -5
- foxes/input/yaml/windio/read_attributes.py +2 -2
- foxes/input/yaml/windio/read_farm.py +5 -5
- foxes/input/yaml/windio/read_fields.py +4 -2
- foxes/input/yaml/windio/read_site.py +52 -0
- foxes/input/yaml/windio/windio.py +1 -1
- 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 +175 -49
- 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 +45 -9
- foxes/models/partial_wakes/segregated.py +2 -20
- foxes/models/partial_wakes/top_hat.py +27 -2
- foxes/models/point_models/__init__.py +4 -4
- foxes/models/rotor_models/__init__.py +3 -3
- foxes/models/rotor_models/centre.py +6 -4
- foxes/models/turbine_models/__init__.py +11 -11
- foxes/models/turbine_models/set_farm_vars.py +0 -1
- foxes/models/turbine_types/PCt_file.py +0 -2
- foxes/models/turbine_types/PCt_from_two.py +0 -2
- foxes/models/turbine_types/__init__.py +9 -9
- 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 +45 -8
- foxes/models/wake_frames/streamlines.py +8 -6
- foxes/models/wake_frames/timelines.py +19 -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 +14 -6
- foxes/output/farm_results_eval.py +51 -27
- foxes/output/flow_plots_2d/__init__.py +2 -2
- foxes/output/flow_plots_2d/get_fig.py +4 -2
- foxes/output/rose_plot.py +23 -5
- 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/slice_data.py +16 -19
- foxes/output/turbine_type_curves.py +7 -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 +3 -3
- foxes/utils/exec_python.py +5 -5
- foxes/utils/factory.py +1 -3
- 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.2.5.dist-info → foxes-1.4.dist-info}/METADATA +14 -21
- foxes-1.4.dist-info/RECORD +320 -0
- {foxes-1.2.5.dist-info → foxes-1.4.dist-info}/WHEEL +1 -1
- tests/0_consistency/iterative/test_iterative.py +2 -3
- tests/0_consistency/partial_wakes/test_partial_wakes.py +2 -2
- 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 +48 -56
- tests/1_verification/flappy_0_6/abl_states/flappy/run.py +0 -1
- tests/1_verification/flappy_0_6/abl_states/test_abl_states.py +33 -36
- 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 +3 -3
- tests/1_verification/flappy_0_6/row_Jensen_linear_tophat/test_row_Jensen_linear_tophat.py +3 -4
- tests/1_verification/flappy_0_6/row_Jensen_linear_tophat_IECTI2005/test_row_Jensen_linear_tophat_IECTI_2005.py +3 -4
- tests/1_verification/flappy_0_6/row_Jensen_linear_tophat_IECTI2019/test_row_Jensen_linear_tophat_IECTI_2019.py +3 -4
- tests/1_verification/flappy_0_6/row_Jensen_quadratic_centre/test_row_Jensen_quadratic_centre.py +3 -4
- tests/1_verification/flappy_0_6_2/grid_rotors/flappy/run.py +0 -2
- tests/1_verification/flappy_0_6_2/grid_rotors/test_grid_rotors.py +3 -3
- tests/1_verification/flappy_0_6_2/row_Bastankhah_Crespo/test_row_Bastankhah_Crespo.py +3 -3
- 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 +3 -4
- tests/3_examples/test_examples.py +3 -2
- foxes/output/round.py +0 -10
- foxes/utils/pandas_helpers.py +0 -178
- foxes-1.2.5.dist-info/RECORD +0 -312
- {foxes-1.2.5.dist-info → foxes-1.4.dist-info}/entry_points.txt +0 -0
- {foxes-1.2.5.dist-info → foxes-1.4.dist-info/licenses}/LICENSE +0 -0
- {foxes-1.2.5.dist-info → foxes-1.4.dist-info}/top_level.txt +0 -0
foxes/output/__init__.py
CHANGED
|
@@ -2,24 +2,26 @@
|
|
|
2
2
|
Output tools and functions.
|
|
3
3
|
"""
|
|
4
4
|
|
|
5
|
-
from .
|
|
6
|
-
from .
|
|
7
|
-
from .
|
|
8
|
-
from .
|
|
9
|
-
from .rose_plot import
|
|
10
|
-
from .
|
|
11
|
-
from .
|
|
12
|
-
from .
|
|
13
|
-
from .
|
|
14
|
-
from .
|
|
15
|
-
from .
|
|
16
|
-
from .
|
|
17
|
-
from .
|
|
18
|
-
from .
|
|
19
|
-
from .
|
|
5
|
+
from .output import Output as Output
|
|
6
|
+
from .farm_layout import FarmLayoutOutput as FarmLayoutOutput
|
|
7
|
+
from .farm_results_eval import FarmResultsEval as FarmResultsEval
|
|
8
|
+
from .rose_plot import RosePlotOutput as RosePlotOutput
|
|
9
|
+
from .rose_plot import StatesRosePlotOutput as StatesRosePlotOutput
|
|
10
|
+
from .rose_plot import WindRoseBinPlot as WindRoseBinPlot
|
|
11
|
+
from .results_writer import ResultsWriter as ResultsWriter
|
|
12
|
+
from .state_turbine_map import StateTurbineMap as StateTurbineMap
|
|
13
|
+
from .turbine_type_curves import TurbineTypeCurves as TurbineTypeCurves
|
|
14
|
+
from .animation import Animator as Animator
|
|
15
|
+
from .calc_points import PointCalculator as PointCalculator
|
|
16
|
+
from .slice_data import SliceData as SliceData
|
|
17
|
+
from .slices_data import SlicesData as SlicesData
|
|
18
|
+
from .rotor_point_plots import RotorPointPlot as RotorPointPlot
|
|
19
|
+
from .state_turbine_table import StateTurbineTable as StateTurbineTable
|
|
20
|
+
from .plt import plt as plt
|
|
20
21
|
|
|
21
|
-
from .flow_plots_2d import FlowPlots2D
|
|
22
|
-
from .seq_plugins import SeqFlowAnimationPlugin
|
|
22
|
+
from .flow_plots_2d import FlowPlots2D as FlowPlots2D
|
|
23
|
+
from .seq_plugins import SeqFlowAnimationPlugin as SeqFlowAnimationPlugin
|
|
24
|
+
from .seq_plugins import SeqWakeDebugPlugin as SeqWakeDebugPlugin
|
|
23
25
|
|
|
24
|
-
from . import grids
|
|
25
|
-
from . import seq_plugins
|
|
26
|
+
from . import grids as grids
|
|
27
|
+
from . import seq_plugins as seq_plugins
|
foxes/output/farm_layout.py
CHANGED
|
@@ -5,8 +5,9 @@ import matplotlib.pyplot as plt
|
|
|
5
5
|
from mpl_toolkits.axes_grid1 import make_axes_locatable
|
|
6
6
|
|
|
7
7
|
from foxes.config import config
|
|
8
|
-
import foxes.variables as FV
|
|
9
8
|
from foxes.output.output import Output
|
|
9
|
+
import foxes.variables as FV
|
|
10
|
+
import foxes.constants as FC
|
|
10
11
|
|
|
11
12
|
|
|
12
13
|
class FarmLayoutOutput(Output):
|
|
@@ -66,10 +67,10 @@ class FarmLayoutOutput(Output):
|
|
|
66
67
|
self.D = D
|
|
67
68
|
|
|
68
69
|
if from_results and farm_results is None:
|
|
69
|
-
raise ValueError(
|
|
70
|
+
raise ValueError("Missing farm_results for switch from_results.")
|
|
70
71
|
|
|
71
72
|
if from_results and results_state is None:
|
|
72
|
-
raise ValueError(
|
|
73
|
+
raise ValueError("Please specify results_state for switch from_results.")
|
|
73
74
|
|
|
74
75
|
def get_layout_data(self):
|
|
75
76
|
"""
|
|
@@ -229,9 +230,16 @@ class FarmLayoutOutput(Output):
|
|
|
229
230
|
if self.fres is None:
|
|
230
231
|
raise ValueError(f"Missing farm_results for color_by '{color_by}'")
|
|
231
232
|
if color_by[:5] == "mean_":
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
233
|
+
weights = self.fres[FV.WEIGHT]
|
|
234
|
+
if weights.dims == (FC.STATE,):
|
|
235
|
+
wx = "s"
|
|
236
|
+
elif weights.dims == (FC.STATE, FC.TURBINE):
|
|
237
|
+
wx = "st"
|
|
238
|
+
else:
|
|
239
|
+
raise ValueError(
|
|
240
|
+
f"Unsupported dimensions for '{FV.WEIGHT}': Expecting '{(FC.STATE,)}' or '{(FC.STATE, FC.TURBINE)}', got '{weights.dims}'"
|
|
241
|
+
)
|
|
242
|
+
kw["c"] = np.einsum(f"st,{wx}->t", self.fres[color_by[5:]], weights)
|
|
235
243
|
elif color_by[:4] == "sum_":
|
|
236
244
|
kw["c"] = np.sum(self.fres[color_by[4:]], axis=0)
|
|
237
245
|
elif color_by[:4] == "min_":
|
|
@@ -66,9 +66,9 @@ class FarmResultsEval(Output):
|
|
|
66
66
|
if isinstance(v, str):
|
|
67
67
|
vdata = self.results[v].to_numpy()
|
|
68
68
|
nns = np.sum(np.isnan(vdata))
|
|
69
|
-
assert (
|
|
70
|
-
nns
|
|
71
|
-
)
|
|
69
|
+
assert nns == 0, (
|
|
70
|
+
f"Found {nns} nan values for variable '{v}' of shape {vdata.shape}"
|
|
71
|
+
)
|
|
72
72
|
fields.append(vdata)
|
|
73
73
|
else:
|
|
74
74
|
fields.append(v)
|
|
@@ -76,22 +76,46 @@ class FarmResultsEval(Output):
|
|
|
76
76
|
nas = np.zeros_like(fields[-1], dtype=bool)
|
|
77
77
|
nas = nas | np.isnan(fields[-1])
|
|
78
78
|
|
|
79
|
-
inds = ["st" for
|
|
80
|
-
|
|
79
|
+
inds = ["st" for __ in fields]
|
|
80
|
+
if self.results[FV.WEIGHT].dims == (FC.STATE,):
|
|
81
|
+
inds += ["s"]
|
|
82
|
+
|
|
83
|
+
if np.any(nas):
|
|
84
|
+
sel = ~np.any(nas, axis=1)
|
|
85
|
+
fields = [f[sel] for f in fields]
|
|
86
|
+
|
|
87
|
+
weights0 = self.results[FV.WEIGHT].to_numpy()
|
|
88
|
+
w0 = np.sum(weights0)
|
|
89
|
+
weights = weights0[sel]
|
|
90
|
+
w1 = np.sum(weights)
|
|
91
|
+
weights *= w0 / w1
|
|
92
|
+
fields.append(weights)
|
|
81
93
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
94
|
+
else:
|
|
95
|
+
fields.append(self.results[FV.WEIGHT].to_numpy())
|
|
96
|
+
|
|
97
|
+
elif self.results[FV.WEIGHT].dims == (FC.STATE, FC.TURBINE):
|
|
98
|
+
inds += ["st"]
|
|
85
99
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
100
|
+
if np.any(nas):
|
|
101
|
+
sel = ~np.any(nas, axis=1)
|
|
102
|
+
fields = [f[sel] for f in fields]
|
|
103
|
+
|
|
104
|
+
weights0 = self.results[FV.WEIGHT].to_numpy()
|
|
105
|
+
w0 = np.sum(weights0, axis=0)[None, :]
|
|
106
|
+
weights = weights0[sel]
|
|
107
|
+
w1 = np.sum(weights, axis=0)[None, :]
|
|
108
|
+
weights *= w0 / w1
|
|
109
|
+
fields.append(weights)
|
|
110
|
+
|
|
111
|
+
else:
|
|
112
|
+
fields.append(self.results[FV.WEIGHT].to_numpy())
|
|
92
113
|
|
|
93
114
|
else:
|
|
94
|
-
|
|
115
|
+
raise ValueError(
|
|
116
|
+
f"Expecting '{FV.WEIGHT}' variable with dimensions {(FC.STATE,)} or {(FC.STATE, FC.TURBINE)}, got {self.results[FV.WEIGHT].dims}"
|
|
117
|
+
)
|
|
118
|
+
expr = ",".join(inds) + "->" + rhs
|
|
95
119
|
|
|
96
120
|
return np.einsum(expr, *fields)
|
|
97
121
|
|
|
@@ -118,9 +142,9 @@ class FarmResultsEval(Output):
|
|
|
118
142
|
for v, op in vars_op.items():
|
|
119
143
|
vdata = self.results[v].to_numpy()
|
|
120
144
|
nns = np.sum(np.isnan(vdata))
|
|
121
|
-
assert (
|
|
122
|
-
nns
|
|
123
|
-
)
|
|
145
|
+
assert nns == 0, (
|
|
146
|
+
f"Found {nns} nan values for variable '{v}' of shape {vdata.shape}"
|
|
147
|
+
)
|
|
124
148
|
|
|
125
149
|
if op == "weights":
|
|
126
150
|
rdata[v] = self.weinsum("t", vdata)
|
|
@@ -167,9 +191,9 @@ class FarmResultsEval(Output):
|
|
|
167
191
|
for v, op in vars_op.items():
|
|
168
192
|
vdata = self.results[v].to_numpy()
|
|
169
193
|
nns = np.sum(np.isnan(vdata))
|
|
170
|
-
assert (
|
|
171
|
-
nns
|
|
172
|
-
)
|
|
194
|
+
assert nns == 0, (
|
|
195
|
+
f"Found {nns} nan values for variable '{v}' of shape {vdata.shape}"
|
|
196
|
+
)
|
|
173
197
|
|
|
174
198
|
if op == "weights":
|
|
175
199
|
rdata[v] = self.weinsum("s", vdata)
|
|
@@ -220,9 +244,9 @@ class FarmResultsEval(Output):
|
|
|
220
244
|
for v, op in turbines_op.items():
|
|
221
245
|
vdata = sdata[v].to_numpy()
|
|
222
246
|
nns = np.sum(np.isnan(vdata))
|
|
223
|
-
assert (
|
|
224
|
-
nns
|
|
225
|
-
)
|
|
247
|
+
assert nns == 0, (
|
|
248
|
+
f"Found {nns} nan values for variable '{v}' of shape {vdata.shape}"
|
|
249
|
+
)
|
|
226
250
|
|
|
227
251
|
if op == "weights":
|
|
228
252
|
if states_op[v] == "weights":
|
|
@@ -447,11 +471,11 @@ class FarmResultsEval(Output):
|
|
|
447
471
|
duration = times[-1] - times[0] + delta_t
|
|
448
472
|
duration_seconds = np.int64(duration.astype(np.int64) / 1e9)
|
|
449
473
|
duration_hours = duration_seconds / 3600
|
|
450
|
-
elif hours is None and annual
|
|
474
|
+
elif hours is None and annual:
|
|
451
475
|
duration_hours = 8760
|
|
452
476
|
elif hours is None:
|
|
453
477
|
raise ValueError(
|
|
454
|
-
|
|
478
|
+
"Expecting parameter 'hours' for non-timeseries data, or 'annual=True'"
|
|
455
479
|
)
|
|
456
480
|
else:
|
|
457
481
|
duration_hours = hours
|
|
@@ -630,7 +654,7 @@ class FarmResultsEval(Output):
|
|
|
630
654
|
else:
|
|
631
655
|
hax = ax
|
|
632
656
|
|
|
633
|
-
hax.set_xlabel(
|
|
657
|
+
hax.set_xlabel("State")
|
|
634
658
|
hax.set_ylabel(variable)
|
|
635
659
|
cc = cycler(color="bgrcmyk")
|
|
636
660
|
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
from .flow_plots import FlowPlots2D
|
|
2
|
-
from .get_fig import get_fig
|
|
1
|
+
from .flow_plots import FlowPlots2D as FlowPlots2D
|
|
2
|
+
from .get_fig import get_fig as get_fig
|
|
@@ -181,6 +181,7 @@ def get_fig(
|
|
|
181
181
|
hax.invert_yaxis()
|
|
182
182
|
|
|
183
183
|
# add rotor position:
|
|
184
|
+
imr = []
|
|
184
185
|
if show_rotor_dict is not None:
|
|
185
186
|
D = show_rotor_dict["D"]
|
|
186
187
|
coords = np.zeros(shape=(2, len(D))) # array to hold change to turbine coords
|
|
@@ -211,12 +212,13 @@ def get_fig(
|
|
|
211
212
|
turb_x2 = x[t] - coords[0, t]
|
|
212
213
|
turb_y1 = y[t] + coords[1, t]
|
|
213
214
|
turb_y2 = y[t] - coords[1, t]
|
|
214
|
-
hax.plot(
|
|
215
|
+
imr += hax.plot(
|
|
215
216
|
[turb_x1, turb_x2],
|
|
216
217
|
[turb_y1, turb_y2],
|
|
217
218
|
color=c,
|
|
218
219
|
linestyle="-",
|
|
219
220
|
linewidth=1,
|
|
221
|
+
animated=animated,
|
|
220
222
|
)
|
|
221
223
|
|
|
222
224
|
if add_bar:
|
|
@@ -233,7 +235,7 @@ def get_fig(
|
|
|
233
235
|
if ret_state:
|
|
234
236
|
out.append(si)
|
|
235
237
|
if ret_im:
|
|
236
|
-
out.append([i for i in [im, qv, ttl] if i is not None])
|
|
238
|
+
out.append([i for i in [im, qv, ttl] if i is not None] + imr)
|
|
237
239
|
if ret_state or ret_im:
|
|
238
240
|
out = tuple(out)
|
|
239
241
|
|
foxes/output/rose_plot.py
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import numpy as np
|
|
2
2
|
import matplotlib.pyplot as plt
|
|
3
3
|
from xarray import Dataset
|
|
4
|
-
from matplotlib.cm import ScalarMappable
|
|
5
4
|
from matplotlib.projections.polar import PolarAxes
|
|
6
5
|
from matplotlib.lines import Line2D
|
|
7
6
|
|
|
@@ -58,7 +57,7 @@ class RosePlotOutput(Output):
|
|
|
58
57
|
self.results = farm_results
|
|
59
58
|
self._rtype = FC.TURBINE
|
|
60
59
|
else:
|
|
61
|
-
raise KeyError(
|
|
60
|
+
raise KeyError("Require either farm_results or point_results")
|
|
62
61
|
|
|
63
62
|
@classmethod
|
|
64
63
|
def get_data_info(cls, dname):
|
|
@@ -151,9 +150,19 @@ class RosePlotOutput(Output):
|
|
|
151
150
|
The plot data
|
|
152
151
|
|
|
153
152
|
"""
|
|
153
|
+
if self.results[FV.WEIGHT].dims == (FC.STATE,):
|
|
154
|
+
w = self.results[FV.WEIGHT].to_numpy()
|
|
155
|
+
elif self.results[FV.WEIGHT].dims == (FC.STATE, FC.TURBINE):
|
|
156
|
+
w = self.results[FV.WEIGHT].to_numpy()[:, turbine]
|
|
157
|
+
elif self.results[FV.WEIGHT].dims == (FC.STATE, FC.POINT):
|
|
158
|
+
w = self.results[FV.WEIGHT].to_numpy()[:, point]
|
|
159
|
+
else:
|
|
160
|
+
raise ValueError(
|
|
161
|
+
f"Wrong dimensions for '{FV.WEIGHT}'. Expecting {(FC.STATE,)}, {(FC.STATE, FC.TURBINE)} or {(FC.STATE, FC.POINT)}, got {self.results[FV.WEIGHT].dims}"
|
|
162
|
+
)
|
|
163
|
+
|
|
154
164
|
if add_inf:
|
|
155
165
|
ws_bins = list(ws_bins) + [np.inf]
|
|
156
|
-
w = self.results[FV.WEIGHT].to_numpy()[:, turbine]
|
|
157
166
|
t = turbine if self._rtype == FC.TURBINE else point
|
|
158
167
|
ws = self.results[ws_var].to_numpy()[:, t]
|
|
159
168
|
wd = self.results[wd_var].to_numpy()[:, t].copy()
|
|
@@ -286,7 +295,8 @@ class RosePlotOutput(Output):
|
|
|
286
295
|
|
|
287
296
|
llines = [Line2D([0], [0], color=c, lw=10) for c in np.flip(color_list, axis=0)]
|
|
288
297
|
lleg = [
|
|
289
|
-
f"[{ws_bins[i]:.1f}, {ws_bins[i+1]:.1f})"
|
|
298
|
+
f"[{ws_bins[i]:.1f}, {ws_bins[i + 1]:.1f})"
|
|
299
|
+
for i in range(n_wsb - 1, -1, -1)
|
|
290
300
|
]
|
|
291
301
|
lpars = dict(
|
|
292
302
|
loc="upper left",
|
|
@@ -449,8 +459,16 @@ class WindRoseBinPlot(Output):
|
|
|
449
459
|
The plot data
|
|
450
460
|
|
|
451
461
|
"""
|
|
462
|
+
if self.farm_results[FV.WEIGHT].dims == (FC.STATE,):
|
|
463
|
+
w = self.farm_results[FV.WEIGHT].to_numpy()
|
|
464
|
+
elif self.farm_results[FV.WEIGHT].dims == (FC.STATE, FC.TURBINE):
|
|
465
|
+
w = self.farm_results[FV.WEIGHT].to_numpy()[:, turbine]
|
|
466
|
+
else:
|
|
467
|
+
raise ValueError(
|
|
468
|
+
f"Wrong dimensions for '{FV.WEIGHT}'. Expecting {(FC.STATE,)} or {(FC.STATE, FC.TURBINE)}, got {self.farm_results[FV.WEIGHT].dims}"
|
|
469
|
+
)
|
|
470
|
+
|
|
452
471
|
var = self.farm_results[variable].to_numpy()[:, turbine]
|
|
453
|
-
w = self.farm_results[FV.WEIGHT].to_numpy()[:, turbine]
|
|
454
472
|
ws = self.farm_results[ws_var].to_numpy()[:, turbine]
|
|
455
473
|
wd = self.farm_results[wd_var].to_numpy()[:, turbine].copy()
|
|
456
474
|
wd_delta = 360 / wd_sectors
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
from .seq_flow_ani_plugin import SeqFlowAnimationPlugin
|
|
2
|
-
from .seq_wake_debug_plugin import SeqWakeDebugPlugin
|
|
1
|
+
from .seq_flow_ani_plugin import SeqFlowAnimationPlugin as SeqFlowAnimationPlugin
|
|
2
|
+
from .seq_wake_debug_plugin import SeqWakeDebugPlugin as SeqWakeDebugPlugin
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
from copy import deepcopy
|
|
2
|
-
|
|
3
1
|
from foxes.algorithms.sequential import SequentialPlugin
|
|
4
2
|
|
|
5
3
|
from ..flow_plots_2d.flow_plots import FlowPlots2D
|
|
@@ -116,7 +114,6 @@ class SeqFlowAnimationPlugin(SequentialPlugin):
|
|
|
116
114
|
fig = ax.get_figure()
|
|
117
115
|
gdata = None
|
|
118
116
|
while len(self._data):
|
|
119
|
-
|
|
120
117
|
fres, d = self._data.pop(0)
|
|
121
118
|
|
|
122
119
|
if d[2] is not None:
|
foxes/output/slice_data.py
CHANGED
|
@@ -123,7 +123,6 @@ class SliceData(Output):
|
|
|
123
123
|
label_map,
|
|
124
124
|
vmin,
|
|
125
125
|
vmax,
|
|
126
|
-
weight_turbine,
|
|
127
126
|
to_file,
|
|
128
127
|
write_pars,
|
|
129
128
|
ret_states,
|
|
@@ -147,12 +146,22 @@ class SliceData(Output):
|
|
|
147
146
|
del g_pts
|
|
148
147
|
|
|
149
148
|
# take mean over states:
|
|
150
|
-
weights =
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
149
|
+
weights = point_results[FV.WEIGHT].to_numpy()
|
|
150
|
+
if point_results[FV.WEIGHT].dims == (FC.STATE,):
|
|
151
|
+
data = {
|
|
152
|
+
v: np.einsum("s,sp->p", weights, point_results[v].to_numpy())
|
|
153
|
+
for v in variables
|
|
154
|
+
}
|
|
155
|
+
elif point_results[FV.WEIGHT].dims == (FC.STATE, FC.POINT):
|
|
156
|
+
data = {
|
|
157
|
+
v: np.einsum("sp,sp->p", weights, point_results[v].to_numpy())
|
|
158
|
+
for v in variables
|
|
159
|
+
}
|
|
160
|
+
else:
|
|
161
|
+
raise ValueError(
|
|
162
|
+
f"Wrong dimensions for '{FV.WEIGHT}': Expecting {(FC.STATE,)} or {(FC.STATE, FC.POINT)}, got {point_results[FV.WEIGHT].dims}"
|
|
163
|
+
)
|
|
164
|
+
del point_results, weights
|
|
156
165
|
|
|
157
166
|
# apply data modification:
|
|
158
167
|
a_pos, b_pos, c_pos, data = self._data_mod(
|
|
@@ -207,7 +216,6 @@ class SliceData(Output):
|
|
|
207
216
|
vmax={},
|
|
208
217
|
states_sel=None,
|
|
209
218
|
states_isel=None,
|
|
210
|
-
weight_turbine=0,
|
|
211
219
|
to_file=None,
|
|
212
220
|
write_pars={},
|
|
213
221
|
ret_states=False,
|
|
@@ -260,8 +268,6 @@ class SliceData(Output):
|
|
|
260
268
|
Reduce to selected states
|
|
261
269
|
states_isel: list, optional
|
|
262
270
|
Reduce to the selected states indices
|
|
263
|
-
weight_turbine: int, optional
|
|
264
|
-
Index of the turbine from which to take the weight
|
|
265
271
|
to_file: str, optional
|
|
266
272
|
Write data to this file name
|
|
267
273
|
write_pars: dict
|
|
@@ -314,7 +320,6 @@ class SliceData(Output):
|
|
|
314
320
|
label_map,
|
|
315
321
|
vmin,
|
|
316
322
|
vmax,
|
|
317
|
-
weight_turbine,
|
|
318
323
|
to_file,
|
|
319
324
|
write_pars,
|
|
320
325
|
ret_states,
|
|
@@ -352,7 +357,6 @@ class SliceData(Output):
|
|
|
352
357
|
vmax={},
|
|
353
358
|
states_sel=None,
|
|
354
359
|
states_isel=None,
|
|
355
|
-
weight_turbine=0,
|
|
356
360
|
to_file=None,
|
|
357
361
|
write_pars={},
|
|
358
362
|
ret_states=False,
|
|
@@ -407,8 +411,6 @@ class SliceData(Output):
|
|
|
407
411
|
Reduce to selected states
|
|
408
412
|
states_isel: list, optional
|
|
409
413
|
Reduce to the selected states indices
|
|
410
|
-
weight_turbine: int, optional
|
|
411
|
-
Index of the turbine from which to take the weight
|
|
412
414
|
to_file: str, optional
|
|
413
415
|
Write data to this file name
|
|
414
416
|
write_pars: dict
|
|
@@ -463,7 +465,6 @@ class SliceData(Output):
|
|
|
463
465
|
label_map,
|
|
464
466
|
vmin,
|
|
465
467
|
vmax,
|
|
466
|
-
weight_turbine,
|
|
467
468
|
to_file,
|
|
468
469
|
write_pars,
|
|
469
470
|
ret_states,
|
|
@@ -501,7 +502,6 @@ class SliceData(Output):
|
|
|
501
502
|
vmax={},
|
|
502
503
|
states_sel=None,
|
|
503
504
|
states_isel=None,
|
|
504
|
-
weight_turbine=0,
|
|
505
505
|
to_file=None,
|
|
506
506
|
write_pars={},
|
|
507
507
|
ret_states=False,
|
|
@@ -556,8 +556,6 @@ class SliceData(Output):
|
|
|
556
556
|
Reduce to selected states
|
|
557
557
|
states_isel: list, optional
|
|
558
558
|
Reduce to the selected states indices
|
|
559
|
-
weight_turbine: int, optional
|
|
560
|
-
Index of the turbine from which to take the weight
|
|
561
559
|
to_file: str, optional
|
|
562
560
|
Write data to this file name
|
|
563
561
|
write_pars: dict
|
|
@@ -612,7 +610,6 @@ class SliceData(Output):
|
|
|
612
610
|
label_map,
|
|
613
611
|
vmin,
|
|
614
612
|
vmax,
|
|
615
|
-
weight_turbine,
|
|
616
613
|
to_file,
|
|
617
614
|
write_pars,
|
|
618
615
|
ret_states,
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
from tabnanny import verbose
|
|
2
1
|
import matplotlib.pyplot as plt
|
|
3
2
|
import numpy as np
|
|
4
3
|
import pandas as pd
|
|
@@ -182,19 +181,19 @@ class TurbineTypeCurves(Output):
|
|
|
182
181
|
t = f"{vv}, {turbine_type}" if titles[i] is None else titles[i]
|
|
183
182
|
ax.set_title(t)
|
|
184
183
|
|
|
185
|
-
|
|
186
|
-
ax.set_xlabel(
|
|
184
|
+
lb = "Wind speed [m/s]" if x_label is None else x_label
|
|
185
|
+
ax.set_xlabel(lb)
|
|
187
186
|
|
|
188
187
|
if y_labels[i] is None:
|
|
189
188
|
if v == FV.P:
|
|
190
|
-
|
|
189
|
+
lb = "Power [kW]"
|
|
191
190
|
elif v == FV.CT:
|
|
192
|
-
|
|
191
|
+
lb = "ct [-]"
|
|
193
192
|
else:
|
|
194
|
-
|
|
193
|
+
lb = v
|
|
195
194
|
else:
|
|
196
|
-
|
|
197
|
-
ax.set_ylabel(
|
|
195
|
+
lb = y_labels[i]
|
|
196
|
+
ax.set_ylabel(lb)
|
|
198
197
|
|
|
199
198
|
ax.grid()
|
|
200
199
|
|
foxes/utils/__init__.py
CHANGED
|
@@ -2,23 +2,41 @@
|
|
|
2
2
|
General utilities.
|
|
3
3
|
"""
|
|
4
4
|
|
|
5
|
-
from .wind_dir import wd2uv
|
|
6
|
-
from .
|
|
7
|
-
from .
|
|
8
|
-
from .
|
|
9
|
-
from .
|
|
10
|
-
from .factory import Factory, FDict, WakeKFactory
|
|
11
|
-
from .data_book import DataBook
|
|
12
|
-
from .cubic_roots import cubic_roots
|
|
13
|
-
from .geopandas_utils import read_shp, shp2csv, read_shp_polygons, shp2geom2d
|
|
14
|
-
from .load import import_module, load_module
|
|
15
|
-
from .exec_python import exec_python
|
|
16
|
-
from .regularize import sqrt_reg
|
|
17
|
-
from .tab_files import read_tab_file
|
|
18
|
-
from .random_xy import random_xy_square
|
|
19
|
-
from .dev_utils import print_mem
|
|
20
|
-
from .wrg_utils import ReaderWRG
|
|
5
|
+
from .wind_dir import wd2uv as wd2uv
|
|
6
|
+
from .wind_dir import wd2wdvec as wd2wdvec
|
|
7
|
+
from .wind_dir import wdvec2wd as wdvec2wd
|
|
8
|
+
from .wind_dir import uv2wd as uv2wd
|
|
9
|
+
from .wind_dir import delta_wd as delta_wd
|
|
21
10
|
|
|
22
|
-
from . import
|
|
23
|
-
from . import
|
|
24
|
-
from . import
|
|
11
|
+
from .subclasses import all_subclasses as all_subclasses
|
|
12
|
+
from .subclasses import new_cls as new_cls
|
|
13
|
+
from .subclasses import new_instance as new_instance
|
|
14
|
+
|
|
15
|
+
from .factory import Factory as Factory
|
|
16
|
+
from .factory import FDict as FDict
|
|
17
|
+
from .factory import WakeKFactory as WakeKFactory
|
|
18
|
+
|
|
19
|
+
from .geopandas_utils import read_shp as read_shp
|
|
20
|
+
from .geopandas_utils import shp2csv as shp2csv
|
|
21
|
+
from .geopandas_utils import read_shp_polygons as read_shp_polygons
|
|
22
|
+
from .geopandas_utils import shp2geom2d as shp2geom2d
|
|
23
|
+
|
|
24
|
+
from .load import import_module as import_module
|
|
25
|
+
from .load import load_module as load_module
|
|
26
|
+
|
|
27
|
+
from .pandas_utils import PandasFileHelper as PandasFileHelper
|
|
28
|
+
from .xarray_utils import write_nc as write_nc
|
|
29
|
+
from .dict import Dict as Dict
|
|
30
|
+
from .data_book import DataBook as DataBook
|
|
31
|
+
from .cubic_roots import cubic_roots as cubic_roots
|
|
32
|
+
from .exec_python import exec_python as exec_python
|
|
33
|
+
from .regularize import sqrt_reg as sqrt_reg
|
|
34
|
+
from .tab_files import read_tab_file as read_tab_file
|
|
35
|
+
from .random_xy import random_xy_square as random_xy_square
|
|
36
|
+
from .dev_utils import print_mem as print_mem
|
|
37
|
+
from .wrg_utils import ReaderWRG as ReaderWRG
|
|
38
|
+
from .weibull import weibull_weights as weibull_weights
|
|
39
|
+
|
|
40
|
+
from . import two_circles as two_circles
|
|
41
|
+
from . import abl as abl
|
|
42
|
+
from . import geom2d as geom2d
|
foxes/utils/abl/__init__.py
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
Atmospheric boundary layer functions.
|
|
3
3
|
"""
|
|
4
4
|
|
|
5
|
-
from . import neutral
|
|
6
|
-
from . import stable
|
|
7
|
-
from . import unstable
|
|
8
|
-
from . import sheared
|
|
5
|
+
from . import neutral as neutral
|
|
6
|
+
from . import stable as stable
|
|
7
|
+
from . import unstable as unstable
|
|
8
|
+
from . import sheared as sheared
|
foxes/utils/cubic_roots.py
CHANGED
|
@@ -104,7 +104,7 @@ def test_cubic_roots(roots, a0, a1, a2, a3=None, tol=1.0e-12):
|
|
|
104
104
|
c2 = a2[n]
|
|
105
105
|
c3 = a3[n]
|
|
106
106
|
|
|
107
|
-
print(f"Polynomial {n}: a = {(c0,c1,c2,c3)}")
|
|
107
|
+
print(f"Polynomial {n}: a = {(c0, c1, c2, c3)}")
|
|
108
108
|
|
|
109
109
|
rts = np.unique(roots[n])
|
|
110
110
|
rts = rts[~np.isnan(rts)]
|
foxes/utils/data_book.py
CHANGED
|
@@ -66,9 +66,10 @@ class DataBook:
|
|
|
66
66
|
except AttributeError:
|
|
67
67
|
contents = list(resources.contents(package))
|
|
68
68
|
|
|
69
|
-
check_f
|
|
70
|
-
|
|
71
|
-
|
|
69
|
+
def check_f(f):
|
|
70
|
+
"""little helper function to check file endings"""
|
|
71
|
+
return any([len(f) > len(s) and f[-len(s) :] == s for s in file_sfx])
|
|
72
|
+
|
|
72
73
|
contents = [f for f in contents if check_f(f)]
|
|
73
74
|
|
|
74
75
|
try:
|
foxes/utils/dict.py
CHANGED
|
@@ -77,9 +77,9 @@ class Dict(dict):
|
|
|
77
77
|
"""
|
|
78
78
|
try:
|
|
79
79
|
if len(deflt):
|
|
80
|
-
assert (
|
|
81
|
-
len(deflt)
|
|
82
|
-
)
|
|
80
|
+
assert len(deflt) == 1, (
|
|
81
|
+
f"Expecting a single default entry, got {len(deflt)}"
|
|
82
|
+
)
|
|
83
83
|
data = self.get(key, deflt[0])
|
|
84
84
|
else:
|
|
85
85
|
data = self[key]
|
foxes/utils/exec_python.py
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import numpy as np
|
|
2
|
-
import pandas as pd
|
|
3
|
-
import xarray as xr
|
|
4
|
-
import matplotlib.pyplot as plt
|
|
1
|
+
import numpy as np # noqa: F401
|
|
2
|
+
import pandas as pd # noqa: F401
|
|
3
|
+
import xarray as xr # noqa: F401
|
|
4
|
+
import matplotlib.pyplot as plt # noqa: F401
|
|
5
5
|
|
|
6
6
|
|
|
7
7
|
def exec_python(s, indicator="%", newline=";", globals=globals(), locals={}):
|
|
@@ -38,7 +38,7 @@ def exec_python(s, indicator="%", newline=";", globals=globals(), locals={}):
|
|
|
38
38
|
L = len(indicator)
|
|
39
39
|
if len(s) > L and s[:L] == indicator:
|
|
40
40
|
a = s[L:]
|
|
41
|
-
if not
|
|
41
|
+
if indicator not in a:
|
|
42
42
|
exec(a, globals, locals)
|
|
43
43
|
else:
|
|
44
44
|
ilist = a.split(indicator)
|
foxes/utils/factory.py
CHANGED
|
@@ -526,9 +526,7 @@ class WakeKFactory:
|
|
|
526
526
|
s += f"\n {v} from {list(f0.options[v])}"
|
|
527
527
|
else:
|
|
528
528
|
s += f"\n {v}={f0.hints.get(v, '(value)')}"
|
|
529
|
-
s += (
|
|
530
|
-
f"\n [wake_k]=(None or k<k> or ka<ka> or ka<ka>_kb<kb>, e.g. 004 for 0.04)"
|
|
531
|
-
)
|
|
529
|
+
s += "\n [wake_k]=(None or k<k> or ka<ka> or ka<ka>_kb<kb>, e.g. 004 for 0.04)"
|
|
532
530
|
return s
|
|
533
531
|
|
|
534
532
|
|
foxes/utils/geom2d/__init__.py
CHANGED
|
@@ -2,8 +2,10 @@
|
|
|
2
2
|
Geometries in two dimensions.
|
|
3
3
|
"""
|
|
4
4
|
|
|
5
|
-
from .area_geometry import AreaGeometry
|
|
6
|
-
from .area_geometry import
|
|
7
|
-
from .
|
|
8
|
-
from .
|
|
9
|
-
from .
|
|
5
|
+
from .area_geometry import AreaGeometry as AreaGeometry
|
|
6
|
+
from .area_geometry import InvertedAreaGeometry as InvertedAreaGeometry
|
|
7
|
+
from .area_geometry import AreaUnion as AreaUnion
|
|
8
|
+
from .area_geometry import AreaIntersection as AreaIntersection
|
|
9
|
+
from .polygon import ClosedPolygon as ClosedPolygon
|
|
10
|
+
from .circle import Circle as Circle
|
|
11
|
+
from .half_plane import HalfPlane as HalfPlane
|