foxes 1.3__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 +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 +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 +21 -17
- foxes/algorithms/__init__.py +6 -6
- foxes/algorithms/downwind/__init__.py +2 -2
- foxes/algorithms/downwind/downwind.py +44 -12
- 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 +0 -1
- foxes/algorithms/downwind/models/point_wakes_calc.py +7 -13
- 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 +0 -1
- foxes/core/data.py +19 -18
- foxes/core/engine.py +9 -13
- foxes/core/farm_controller.py +2 -2
- 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 +3 -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/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 -12
- foxes/input/states/create/__init__.py +3 -2
- foxes/input/states/field_data_nc.py +10 -24
- foxes/input/states/multi_height.py +9 -6
- foxes/input/states/one_point_flow.py +0 -4
- foxes/input/states/single.py +1 -1
- foxes/input/states/states_table.py +10 -7
- foxes/input/states/weibull_sectors.py +225 -0
- foxes/input/states/wrg_states.py +7 -5
- 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 +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 +3 -3
- 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 +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 +2 -2
- foxes/output/farm_results_eval.py +15 -15
- foxes/output/flow_plots_2d/__init__.py +2 -2
- foxes/output/flow_plots_2d/get_fig.py +4 -2
- foxes/output/rose_plot.py +3 -3
- 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/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.3.dist-info → foxes-1.4.dist-info}/METADATA +6 -15
- foxes-1.4.dist-info/RECORD +320 -0
- {foxes-1.3.dist-info → foxes-1.4.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/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.4.dist-info}/entry_points.txt +0 -0
- {foxes-1.3.dist-info → foxes-1.4.dist-info/licenses}/LICENSE +0 -0
- {foxes-1.3.dist-info → foxes-1.4.dist-info}/top_level.txt +0 -0
|
@@ -145,8 +145,8 @@ class WSPow(WakeSuperposition):
|
|
|
145
145
|
algo,
|
|
146
146
|
mdata,
|
|
147
147
|
fdata,
|
|
148
|
+
tdata,
|
|
148
149
|
variable,
|
|
149
|
-
amb_results,
|
|
150
150
|
wake_delta,
|
|
151
151
|
):
|
|
152
152
|
"""
|
|
@@ -161,11 +161,10 @@ class WSPow(WakeSuperposition):
|
|
|
161
161
|
The model data
|
|
162
162
|
fdata: foxes.core.FData
|
|
163
163
|
The farm data
|
|
164
|
+
tdata: foxes.core.TData
|
|
165
|
+
The target point data
|
|
164
166
|
variable: str
|
|
165
167
|
The variable name for which the wake deltas applies
|
|
166
|
-
amb_results: numpy.ndarray
|
|
167
|
-
The ambient results at targets,
|
|
168
|
-
shape: (n_states, n_targets, n_tpoints)
|
|
169
168
|
wake_delta: numpy.ndarray
|
|
170
169
|
The wake deltas at targets, shape:
|
|
171
170
|
(n_states, n_targets, n_tpoints)
|
|
@@ -178,6 +177,7 @@ class WSPow(WakeSuperposition):
|
|
|
178
177
|
(n_states, n_targets, n_tpoints)
|
|
179
178
|
|
|
180
179
|
"""
|
|
180
|
+
amb_results = tdata[FV.var2amb[variable]]
|
|
181
181
|
w = -(wake_delta ** (1 / self.pow))
|
|
182
182
|
if self.lim_low is not None:
|
|
183
183
|
w = np.maximum(w, self.lim_low - amb_results)
|
|
@@ -307,8 +307,8 @@ class WSPowLocal(WakeSuperposition):
|
|
|
307
307
|
algo,
|
|
308
308
|
mdata,
|
|
309
309
|
fdata,
|
|
310
|
+
tdata,
|
|
310
311
|
variable,
|
|
311
|
-
amb_results,
|
|
312
312
|
wake_delta,
|
|
313
313
|
):
|
|
314
314
|
"""
|
|
@@ -323,11 +323,10 @@ class WSPowLocal(WakeSuperposition):
|
|
|
323
323
|
The model data
|
|
324
324
|
fdata: foxes.core.FData
|
|
325
325
|
The farm data
|
|
326
|
+
tdata: foxes.core.TData
|
|
327
|
+
The target point data
|
|
326
328
|
variable: str
|
|
327
329
|
The variable name for which the wake deltas applies
|
|
328
|
-
amb_results: numpy.ndarray
|
|
329
|
-
The ambient results at targets,
|
|
330
|
-
shape: (n_states, n_targets, n_tpoints)
|
|
331
330
|
wake_delta: numpy.ndarray
|
|
332
331
|
The wake deltas at targets, shape:
|
|
333
332
|
(n_states, n_targets, n_tpoints)
|
|
@@ -340,6 +339,7 @@ class WSPowLocal(WakeSuperposition):
|
|
|
340
339
|
(n_states, n_targets, n_tpoints)
|
|
341
340
|
|
|
342
341
|
"""
|
|
342
|
+
amb_results = tdata[FV.var2amb[variable]]
|
|
343
343
|
w = -(wake_delta ** (1 / self.pow)) * amb_results
|
|
344
344
|
if self.lim_low is not None:
|
|
345
345
|
w = np.maximum(w, self.lim_low - amb_results)
|
|
@@ -131,8 +131,8 @@ class WSProduct(WakeSuperposition):
|
|
|
131
131
|
algo,
|
|
132
132
|
mdata,
|
|
133
133
|
fdata,
|
|
134
|
+
tdata,
|
|
134
135
|
variable,
|
|
135
|
-
amb_results,
|
|
136
136
|
wake_delta,
|
|
137
137
|
):
|
|
138
138
|
"""
|
|
@@ -147,11 +147,10 @@ class WSProduct(WakeSuperposition):
|
|
|
147
147
|
The model data
|
|
148
148
|
fdata: foxes.core.FData
|
|
149
149
|
The farm data
|
|
150
|
+
tdata: foxes.core.TData
|
|
151
|
+
The target point data
|
|
150
152
|
variable: str
|
|
151
153
|
The variable name for which the wake deltas applies
|
|
152
|
-
amb_results: numpy.ndarray
|
|
153
|
-
The ambient results at targets,
|
|
154
|
-
shape: (n_states, n_targets, n_tpoints)
|
|
155
154
|
wake_delta: numpy.ndarray
|
|
156
155
|
The wake deltas at targets, shape:
|
|
157
156
|
(n_states, n_targets, n_tpoints)
|
|
@@ -164,6 +163,7 @@ class WSProduct(WakeSuperposition):
|
|
|
164
163
|
(n_states, n_targets, n_tpoints)
|
|
165
164
|
|
|
166
165
|
"""
|
|
166
|
+
amb_results = tdata[FV.var2amb[variable]]
|
|
167
167
|
w = amb_results * (wake_delta - 1)
|
|
168
168
|
if self.lim_low is not None:
|
|
169
169
|
w = np.maximum(w, self.lim_low - amb_results)
|
|
@@ -140,8 +140,8 @@ class WSQuadratic(WakeSuperposition):
|
|
|
140
140
|
algo,
|
|
141
141
|
mdata,
|
|
142
142
|
fdata,
|
|
143
|
+
tdata,
|
|
143
144
|
variable,
|
|
144
|
-
amb_results,
|
|
145
145
|
wake_delta,
|
|
146
146
|
):
|
|
147
147
|
"""
|
|
@@ -156,11 +156,10 @@ class WSQuadratic(WakeSuperposition):
|
|
|
156
156
|
The model data
|
|
157
157
|
fdata: foxes.core.FData
|
|
158
158
|
The farm data
|
|
159
|
+
tdata: foxes.core.TData
|
|
160
|
+
The target point data
|
|
159
161
|
variable: str
|
|
160
162
|
The variable name for which the wake deltas applies
|
|
161
|
-
amb_results: numpy.ndarray
|
|
162
|
-
The ambient results at targets,
|
|
163
|
-
shape: (n_states, n_targets, n_tpoints)
|
|
164
163
|
wake_delta: numpy.ndarray
|
|
165
164
|
The wake deltas at targets, shape:
|
|
166
165
|
(n_states, n_targets, n_tpoints)
|
|
@@ -173,6 +172,7 @@ class WSQuadratic(WakeSuperposition):
|
|
|
173
172
|
(n_states, n_targets, n_tpoints)
|
|
174
173
|
|
|
175
174
|
"""
|
|
175
|
+
amb_results = tdata[FV.var2amb[variable]]
|
|
176
176
|
w = -np.sqrt(wake_delta)
|
|
177
177
|
if self.lim_low is not None:
|
|
178
178
|
w = np.maximum(w, self.lim_low - amb_results)
|
|
@@ -296,8 +296,8 @@ class WSQuadraticLocal(WakeSuperposition):
|
|
|
296
296
|
algo,
|
|
297
297
|
mdata,
|
|
298
298
|
fdata,
|
|
299
|
+
tdata,
|
|
299
300
|
variable,
|
|
300
|
-
amb_results,
|
|
301
301
|
wake_delta,
|
|
302
302
|
):
|
|
303
303
|
"""
|
|
@@ -312,11 +312,10 @@ class WSQuadraticLocal(WakeSuperposition):
|
|
|
312
312
|
The model data
|
|
313
313
|
fdata: foxes.core.FData
|
|
314
314
|
The farm data
|
|
315
|
+
tdata: foxes.core.TData
|
|
316
|
+
The target point data
|
|
315
317
|
variable: str
|
|
316
318
|
The variable name for which the wake deltas applies
|
|
317
|
-
amb_results: numpy.ndarray
|
|
318
|
-
The ambient results at targets,
|
|
319
|
-
shape: (n_states, n_targets, n_tpoints)
|
|
320
319
|
wake_delta: numpy.ndarray
|
|
321
320
|
The wake deltas at targets, shape:
|
|
322
321
|
(n_states, n_targets, n_tpoints)
|
|
@@ -329,6 +328,7 @@ class WSQuadraticLocal(WakeSuperposition):
|
|
|
329
328
|
(n_states, n_targets, n_tpoints)
|
|
330
329
|
|
|
331
330
|
"""
|
|
331
|
+
amb_results = tdata[FV.var2amb[variable]]
|
|
332
332
|
w = -np.sqrt(wake_delta) * amb_results
|
|
333
333
|
if self.lim_low is not None:
|
|
334
334
|
w = np.maximum(w, self.lim_low - amb_results)
|
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
|
@@ -67,10 +67,10 @@ class FarmLayoutOutput(Output):
|
|
|
67
67
|
self.D = D
|
|
68
68
|
|
|
69
69
|
if from_results and farm_results is None:
|
|
70
|
-
raise ValueError(
|
|
70
|
+
raise ValueError("Missing farm_results for switch from_results.")
|
|
71
71
|
|
|
72
72
|
if from_results and results_state is None:
|
|
73
|
-
raise ValueError(
|
|
73
|
+
raise ValueError("Please specify results_state for switch from_results.")
|
|
74
74
|
|
|
75
75
|
def get_layout_data(self):
|
|
76
76
|
"""
|
|
@@ -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)
|
|
@@ -142,9 +142,9 @@ class FarmResultsEval(Output):
|
|
|
142
142
|
for v, op in vars_op.items():
|
|
143
143
|
vdata = self.results[v].to_numpy()
|
|
144
144
|
nns = np.sum(np.isnan(vdata))
|
|
145
|
-
assert (
|
|
146
|
-
nns
|
|
147
|
-
)
|
|
145
|
+
assert nns == 0, (
|
|
146
|
+
f"Found {nns} nan values for variable '{v}' of shape {vdata.shape}"
|
|
147
|
+
)
|
|
148
148
|
|
|
149
149
|
if op == "weights":
|
|
150
150
|
rdata[v] = self.weinsum("t", vdata)
|
|
@@ -191,9 +191,9 @@ class FarmResultsEval(Output):
|
|
|
191
191
|
for v, op in vars_op.items():
|
|
192
192
|
vdata = self.results[v].to_numpy()
|
|
193
193
|
nns = np.sum(np.isnan(vdata))
|
|
194
|
-
assert (
|
|
195
|
-
nns
|
|
196
|
-
)
|
|
194
|
+
assert nns == 0, (
|
|
195
|
+
f"Found {nns} nan values for variable '{v}' of shape {vdata.shape}"
|
|
196
|
+
)
|
|
197
197
|
|
|
198
198
|
if op == "weights":
|
|
199
199
|
rdata[v] = self.weinsum("s", vdata)
|
|
@@ -244,9 +244,9 @@ class FarmResultsEval(Output):
|
|
|
244
244
|
for v, op in turbines_op.items():
|
|
245
245
|
vdata = sdata[v].to_numpy()
|
|
246
246
|
nns = np.sum(np.isnan(vdata))
|
|
247
|
-
assert (
|
|
248
|
-
nns
|
|
249
|
-
)
|
|
247
|
+
assert nns == 0, (
|
|
248
|
+
f"Found {nns} nan values for variable '{v}' of shape {vdata.shape}"
|
|
249
|
+
)
|
|
250
250
|
|
|
251
251
|
if op == "weights":
|
|
252
252
|
if states_op[v] == "weights":
|
|
@@ -471,11 +471,11 @@ class FarmResultsEval(Output):
|
|
|
471
471
|
duration = times[-1] - times[0] + delta_t
|
|
472
472
|
duration_seconds = np.int64(duration.astype(np.int64) / 1e9)
|
|
473
473
|
duration_hours = duration_seconds / 3600
|
|
474
|
-
elif hours is None and annual
|
|
474
|
+
elif hours is None and annual:
|
|
475
475
|
duration_hours = 8760
|
|
476
476
|
elif hours is None:
|
|
477
477
|
raise ValueError(
|
|
478
|
-
|
|
478
|
+
"Expecting parameter 'hours' for non-timeseries data, or 'annual=True'"
|
|
479
479
|
)
|
|
480
480
|
else:
|
|
481
481
|
duration_hours = hours
|
|
@@ -654,7 +654,7 @@ class FarmResultsEval(Output):
|
|
|
654
654
|
else:
|
|
655
655
|
hax = ax
|
|
656
656
|
|
|
657
|
-
hax.set_xlabel(
|
|
657
|
+
hax.set_xlabel("State")
|
|
658
658
|
hax.set_ylabel(variable)
|
|
659
659
|
cc = cycler(color="bgrcmyk")
|
|
660
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):
|
|
@@ -296,7 +295,8 @@ class RosePlotOutput(Output):
|
|
|
296
295
|
|
|
297
296
|
llines = [Line2D([0], [0], color=c, lw=10) for c in np.flip(color_list, axis=0)]
|
|
298
297
|
lleg = [
|
|
299
|
-
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)
|
|
300
300
|
]
|
|
301
301
|
lpars = dict(
|
|
302
302
|
loc="upper left",
|
|
@@ -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:
|
|
@@ -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
|
foxes/utils/geopandas_utils.py
CHANGED
|
@@ -179,7 +179,7 @@ def read_shp_polygons(
|
|
|
179
179
|
utmz = None
|
|
180
180
|
utml = None
|
|
181
181
|
apply_utm = False
|
|
182
|
-
if isinstance(to_utm, str) or to_utm
|
|
182
|
+
if isinstance(to_utm, str) or to_utm:
|
|
183
183
|
apply_utm = True
|
|
184
184
|
check_import_utm()
|
|
185
185
|
utmz = int(to_utm[:-1]) if isinstance(to_utm, str) else None
|
|
@@ -190,7 +190,7 @@ def read_shp_polygons(
|
|
|
190
190
|
names = pnames if names is None else names
|
|
191
191
|
for name in names:
|
|
192
192
|
if name == name: # exclude nan values
|
|
193
|
-
if not
|
|
193
|
+
if name not in pnames:
|
|
194
194
|
raise KeyError(
|
|
195
195
|
f"Name '{name}' not found in file '{fname}'. Names: {pnames}"
|
|
196
196
|
)
|
foxes/utils/pandas_utils.py
CHANGED
|
@@ -106,9 +106,10 @@ class PandasFileHelper:
|
|
|
106
106
|
elif sfx == "h5":
|
|
107
107
|
f = pd.read_hdf
|
|
108
108
|
elif sfx == "nc":
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
109
|
+
|
|
110
|
+
def f(fname, **pars):
|
|
111
|
+
"""little helper to read netcdf files"""
|
|
112
|
+
return xarray.open_dataset(fname, **pars).to_dataframe()
|
|
112
113
|
|
|
113
114
|
if f is not None:
|
|
114
115
|
pars = deepcopy(cls.DEFAULT_READING_PARAMETERS[fmt])
|
foxes/utils/tab_files.py
CHANGED
foxes/utils/weibull.py
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
def weibull_weights(ws, ws_deltas, A, k):
|
|
5
|
+
"""
|
|
6
|
+
Computes the weibull weights for given wind speeds
|
|
7
|
+
|
|
8
|
+
Parameters
|
|
9
|
+
----------
|
|
10
|
+
ws: numpy.ndarray
|
|
11
|
+
The wind speed bin centre values
|
|
12
|
+
ws_deltas: numpy.ndarray
|
|
13
|
+
The wind speed bin widths, same shape as ws
|
|
14
|
+
A: numpy.ndarray
|
|
15
|
+
The Weibull scale parameters, same shape as ws
|
|
16
|
+
k: numpy.ndarray
|
|
17
|
+
The Weibull shape parameters, same shape as ws
|
|
18
|
+
|
|
19
|
+
Returns
|
|
20
|
+
-------
|
|
21
|
+
weights: numpy.ndarray
|
|
22
|
+
The weights, same shape as ws
|
|
23
|
+
|
|
24
|
+
:group: utils
|
|
25
|
+
|
|
26
|
+
"""
|
|
27
|
+
wsA = ws / A
|
|
28
|
+
return ws_deltas * (k / A * wsA ** (k - 1) * np.exp(-(wsA**k)))
|