foxes 0.8.2__py3-none-any.whl → 1.1.0.2__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 +353 -0
- examples/abl_states/run.py +160 -0
- examples/compare_rotors_pwakes/run.py +217 -0
- examples/compare_wakes/run.py +241 -0
- examples/dyn_wakes/run.py +311 -0
- examples/field_data_nc/run.py +121 -0
- examples/induction/run.py +201 -0
- examples/multi_height/run.py +113 -0
- examples/power_mask/run.py +249 -0
- examples/random_timeseries/run.py +210 -0
- examples/scan_row/run.py +193 -0
- examples/sector_management/run.py +162 -0
- examples/sequential/run.py +209 -0
- examples/single_state/run.py +201 -0
- examples/states_lookup_table/run.py +137 -0
- examples/streamline_wakes/run.py +138 -0
- examples/tab_file/run.py +142 -0
- examples/timelines/run.py +267 -0
- examples/timeseries/run.py +190 -0
- examples/timeseries_slurm/run.py +185 -0
- examples/wind_rose/run.py +141 -0
- examples/windio/run.py +29 -0
- examples/yawed_wake/run.py +196 -0
- foxes/__init__.py +4 -8
- foxes/algorithms/__init__.py +1 -1
- foxes/algorithms/downwind/downwind.py +247 -111
- foxes/algorithms/downwind/models/farm_wakes_calc.py +12 -7
- foxes/algorithms/downwind/models/init_farm_data.py +2 -2
- foxes/algorithms/downwind/models/point_wakes_calc.py +6 -7
- foxes/algorithms/downwind/models/reorder_farm_output.py +1 -2
- foxes/algorithms/downwind/models/set_amb_farm_results.py +1 -1
- foxes/algorithms/downwind/models/set_amb_point_results.py +5 -3
- foxes/algorithms/iterative/iterative.py +74 -34
- foxes/algorithms/iterative/models/farm_wakes_calc.py +12 -7
- foxes/algorithms/iterative/models/urelax.py +3 -3
- foxes/algorithms/sequential/models/plugin.py +5 -5
- foxes/algorithms/sequential/models/seq_state.py +1 -1
- foxes/algorithms/sequential/sequential.py +126 -255
- foxes/constants.py +22 -7
- foxes/core/__init__.py +1 -0
- foxes/core/algorithm.py +632 -147
- foxes/core/data.py +252 -20
- foxes/core/data_calc_model.py +15 -291
- foxes/core/engine.py +640 -0
- foxes/core/farm_controller.py +38 -10
- foxes/core/farm_data_model.py +16 -1
- foxes/core/ground_model.py +2 -2
- foxes/core/model.py +249 -182
- foxes/core/partial_wakes_model.py +1 -1
- foxes/core/point_data_model.py +17 -2
- foxes/core/rotor_model.py +27 -21
- foxes/core/states.py +17 -1
- foxes/core/turbine_type.py +28 -0
- foxes/core/wake_frame.py +30 -34
- foxes/core/wake_model.py +5 -5
- foxes/core/wake_superposition.py +1 -1
- foxes/data/windio/windio_5turbines_timeseries.yaml +31 -15
- foxes/engines/__init__.py +17 -0
- foxes/engines/dask.py +982 -0
- foxes/engines/default.py +75 -0
- foxes/engines/futures.py +72 -0
- foxes/engines/mpi.py +38 -0
- foxes/engines/multiprocess.py +71 -0
- foxes/engines/numpy.py +167 -0
- foxes/engines/pool.py +249 -0
- foxes/engines/ray.py +79 -0
- foxes/engines/single.py +141 -0
- foxes/input/farm_layout/__init__.py +1 -0
- foxes/input/farm_layout/from_csv.py +4 -0
- foxes/input/farm_layout/from_json.py +2 -2
- foxes/input/farm_layout/grid.py +2 -2
- foxes/input/farm_layout/ring.py +65 -0
- foxes/input/farm_layout/row.py +2 -2
- foxes/input/states/__init__.py +7 -0
- foxes/input/states/create/random_abl_states.py +1 -1
- foxes/input/states/field_data_nc.py +158 -33
- foxes/input/states/multi_height.py +128 -14
- foxes/input/states/one_point_flow.py +577 -0
- foxes/input/states/scan_ws.py +74 -3
- foxes/input/states/single.py +1 -1
- foxes/input/states/slice_data_nc.py +681 -0
- foxes/input/states/states_table.py +204 -35
- foxes/input/windio/__init__.py +2 -2
- foxes/input/windio/get_states.py +44 -23
- foxes/input/windio/read_attributes.py +48 -17
- foxes/input/windio/read_farm.py +116 -102
- foxes/input/windio/read_fields.py +16 -6
- foxes/input/windio/read_outputs.py +71 -24
- foxes/input/windio/runner.py +31 -17
- foxes/input/windio/windio.py +41 -23
- foxes/models/farm_models/turbine2farm.py +1 -1
- foxes/models/ground_models/wake_mirror.py +10 -6
- foxes/models/model_book.py +58 -20
- foxes/models/partial_wakes/axiwake.py +3 -3
- foxes/models/partial_wakes/rotor_points.py +3 -3
- foxes/models/partial_wakes/top_hat.py +2 -2
- foxes/models/point_models/set_uniform_data.py +1 -1
- foxes/models/point_models/tke2ti.py +1 -1
- foxes/models/point_models/wake_deltas.py +1 -1
- foxes/models/rotor_models/centre.py +4 -0
- foxes/models/rotor_models/grid.py +24 -25
- foxes/models/rotor_models/levels.py +4 -5
- foxes/models/turbine_models/calculator.py +4 -6
- foxes/models/turbine_models/kTI_model.py +22 -6
- foxes/models/turbine_models/lookup_table.py +30 -4
- foxes/models/turbine_models/rotor_centre_calc.py +4 -3
- foxes/models/turbine_models/set_farm_vars.py +103 -34
- foxes/models/turbine_types/PCt_file.py +27 -3
- foxes/models/turbine_types/PCt_from_two.py +27 -3
- foxes/models/turbine_types/TBL_file.py +80 -0
- foxes/models/turbine_types/__init__.py +2 -0
- foxes/models/turbine_types/lookup.py +316 -0
- foxes/models/turbine_types/null_type.py +51 -1
- foxes/models/turbine_types/wsrho2PCt_from_two.py +29 -5
- foxes/models/turbine_types/wsti2PCt_from_two.py +31 -7
- foxes/models/vertical_profiles/__init__.py +1 -1
- foxes/models/vertical_profiles/data_profile.py +1 -1
- foxes/models/wake_frames/__init__.py +1 -0
- foxes/models/wake_frames/dynamic_wakes.py +424 -0
- foxes/models/wake_frames/farm_order.py +25 -5
- foxes/models/wake_frames/rotor_wd.py +6 -4
- foxes/models/wake_frames/seq_dynamic_wakes.py +61 -74
- foxes/models/wake_frames/streamlines.py +21 -22
- foxes/models/wake_frames/timelines.py +330 -129
- foxes/models/wake_frames/yawed_wakes.py +7 -4
- foxes/models/wake_models/dist_sliced.py +2 -4
- foxes/models/wake_models/induction/rankine_half_body.py +5 -5
- foxes/models/wake_models/induction/rathmann.py +78 -24
- foxes/models/wake_models/induction/self_similar.py +78 -28
- foxes/models/wake_models/induction/vortex_sheet.py +86 -48
- foxes/models/wake_models/ti/crespo_hernandez.py +6 -4
- foxes/models/wake_models/ti/iec_ti.py +40 -21
- foxes/models/wake_models/top_hat.py +1 -1
- foxes/models/wake_models/wind/bastankhah14.py +8 -6
- foxes/models/wake_models/wind/bastankhah16.py +17 -16
- foxes/models/wake_models/wind/jensen.py +4 -3
- foxes/models/wake_models/wind/turbopark.py +16 -13
- foxes/models/wake_superpositions/ti_linear.py +1 -1
- foxes/models/wake_superpositions/ti_max.py +1 -1
- foxes/models/wake_superpositions/ti_pow.py +1 -1
- foxes/models/wake_superpositions/ti_quadratic.py +1 -1
- foxes/models/wake_superpositions/ws_linear.py +8 -7
- foxes/models/wake_superpositions/ws_max.py +8 -7
- foxes/models/wake_superpositions/ws_pow.py +8 -7
- foxes/models/wake_superpositions/ws_product.py +5 -5
- foxes/models/wake_superpositions/ws_quadratic.py +8 -7
- foxes/output/__init__.py +4 -1
- foxes/output/farm_layout.py +16 -12
- foxes/output/farm_results_eval.py +1 -1
- foxes/output/flow_plots_2d/__init__.py +0 -1
- foxes/output/flow_plots_2d/flow_plots.py +70 -30
- foxes/output/grids.py +92 -22
- foxes/output/results_writer.py +2 -2
- foxes/output/rose_plot.py +3 -3
- foxes/output/seq_plugins/__init__.py +2 -0
- foxes/output/{flow_plots_2d → seq_plugins}/seq_flow_ani_plugin.py +64 -22
- foxes/output/seq_plugins/seq_wake_debug_plugin.py +145 -0
- foxes/output/slice_data.py +131 -111
- foxes/output/state_turbine_map.py +19 -14
- foxes/output/state_turbine_table.py +19 -19
- foxes/utils/__init__.py +1 -1
- foxes/utils/abl/neutral.py +2 -2
- foxes/utils/abl/stable.py +2 -2
- foxes/utils/abl/unstable.py +2 -2
- foxes/utils/data_book.py +1 -1
- foxes/utils/dev_utils.py +42 -0
- foxes/utils/dict.py +24 -1
- foxes/utils/exec_python.py +1 -1
- foxes/utils/factory.py +176 -53
- foxes/utils/geom2d/circle.py +1 -1
- foxes/utils/geom2d/polygon.py +1 -1
- foxes/utils/geopandas_utils.py +2 -2
- foxes/utils/load.py +2 -2
- foxes/utils/pandas_helpers.py +3 -2
- foxes/utils/wind_dir.py +0 -2
- foxes/utils/xarray_utils.py +24 -14
- foxes/variables.py +39 -2
- {foxes-0.8.2.dist-info → foxes-1.1.0.2.dist-info}/METADATA +75 -33
- foxes-1.1.0.2.dist-info/RECORD +309 -0
- {foxes-0.8.2.dist-info → foxes-1.1.0.2.dist-info}/WHEEL +1 -1
- foxes-1.1.0.2.dist-info/top_level.txt +4 -0
- tests/0_consistency/iterative/test_iterative.py +92 -0
- tests/0_consistency/partial_wakes/test_partial_wakes.py +90 -0
- tests/1_verification/flappy_0_6/PCt_files/flappy/run.py +85 -0
- tests/1_verification/flappy_0_6/PCt_files/test_PCt_files.py +103 -0
- tests/1_verification/flappy_0_6/abl_states/flappy/run.py +85 -0
- tests/1_verification/flappy_0_6/abl_states/test_abl_states.py +87 -0
- tests/1_verification/flappy_0_6/partial_top_hat/flappy/run.py +82 -0
- tests/1_verification/flappy_0_6/partial_top_hat/test_partial_top_hat.py +82 -0
- tests/1_verification/flappy_0_6/row_Jensen_linear_centre/flappy/run.py +92 -0
- tests/1_verification/flappy_0_6/row_Jensen_linear_centre/test_row_Jensen_linear_centre.py +93 -0
- tests/1_verification/flappy_0_6/row_Jensen_linear_tophat/flappy/run.py +92 -0
- tests/1_verification/flappy_0_6/row_Jensen_linear_tophat/test_row_Jensen_linear_tophat.py +96 -0
- tests/1_verification/flappy_0_6/row_Jensen_linear_tophat_IECTI2005/flappy/run.py +94 -0
- tests/1_verification/flappy_0_6/row_Jensen_linear_tophat_IECTI2005/test_row_Jensen_linear_tophat_IECTI_2005.py +122 -0
- tests/1_verification/flappy_0_6/row_Jensen_linear_tophat_IECTI2019/flappy/run.py +94 -0
- tests/1_verification/flappy_0_6/row_Jensen_linear_tophat_IECTI2019/test_row_Jensen_linear_tophat_IECTI_2019.py +122 -0
- tests/1_verification/flappy_0_6/row_Jensen_quadratic_centre/flappy/run.py +92 -0
- tests/1_verification/flappy_0_6/row_Jensen_quadratic_centre/test_row_Jensen_quadratic_centre.py +93 -0
- tests/1_verification/flappy_0_6_2/grid_rotors/flappy/run.py +85 -0
- tests/1_verification/flappy_0_6_2/grid_rotors/test_grid_rotors.py +130 -0
- tests/1_verification/flappy_0_6_2/row_Bastankhah_Crespo/flappy/run.py +96 -0
- tests/1_verification/flappy_0_6_2/row_Bastankhah_Crespo/test_row_Bastankhah_Crespo.py +116 -0
- tests/1_verification/flappy_0_6_2/row_Bastankhah_linear_centre/flappy/run.py +93 -0
- tests/1_verification/flappy_0_6_2/row_Bastankhah_linear_centre/test_row_Bastankhah_linear_centre.py +99 -0
- tests/3_examples/test_examples.py +34 -0
- foxes/VERSION +0 -1
- foxes/output/flow_plots_2d.py +0 -0
- foxes/utils/geopandas_helpers.py +0 -294
- foxes/utils/runners/__init__.py +0 -1
- foxes/utils/runners/runners.py +0 -280
- foxes-0.8.2.dist-info/RECORD +0 -247
- foxes-0.8.2.dist-info/top_level.txt +0 -1
- foxes-0.8.2.dist-info/zip-safe +0 -1
- {foxes-0.8.2.dist-info → foxes-1.1.0.2.dist-info}/LICENSE +0 -0
|
@@ -482,6 +482,7 @@ class FlowPlots2D(SliceData):
|
|
|
482
482
|
ret_im=False,
|
|
483
483
|
animated=False,
|
|
484
484
|
rotor_color=None,
|
|
485
|
+
precalc=False,
|
|
485
486
|
**kwargs,
|
|
486
487
|
):
|
|
487
488
|
"""
|
|
@@ -527,6 +528,11 @@ class FlowPlots2D(SliceData):
|
|
|
527
528
|
Switch for usage for an animation
|
|
528
529
|
rotor_color: str, optional
|
|
529
530
|
Indicate the rotor orientation by a colored line
|
|
531
|
+
precalc: bool or tuple
|
|
532
|
+
Flag for pre-calculation run, adding an additional
|
|
533
|
+
generator call before the actual plot generations,
|
|
534
|
+
yields data, states, gdata. The same tuple can be given
|
|
535
|
+
for avoiding its calculation and picking up from there.
|
|
530
536
|
kwargs: dict, optional
|
|
531
537
|
Additional parameters for SliceData.get_states_data_xy
|
|
532
538
|
|
|
@@ -546,15 +552,21 @@ class FlowPlots2D(SliceData):
|
|
|
546
552
|
wdi = variables.index(FV.WD)
|
|
547
553
|
wsi = variables.index(FV.WS)
|
|
548
554
|
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
555
|
+
if isinstance(precalc, (tuple, list)):
|
|
556
|
+
data, states, gdata = precalc
|
|
557
|
+
else:
|
|
558
|
+
data, states, gdata = self.get_states_data_xy(
|
|
559
|
+
variables=variables,
|
|
560
|
+
vmin={var: vmin} if vmin is not None else {},
|
|
561
|
+
vmax={var: vmax} if vmax is not None else {},
|
|
562
|
+
data_format="numpy",
|
|
563
|
+
ret_states=True,
|
|
564
|
+
ret_grid=True,
|
|
565
|
+
**kwargs,
|
|
566
|
+
)
|
|
567
|
+
if precalc:
|
|
568
|
+
yield data, states, gdata
|
|
569
|
+
|
|
558
570
|
x_pos, y_pos, z_pos, __ = gdata
|
|
559
571
|
|
|
560
572
|
# define wind vector arrows:
|
|
@@ -573,8 +585,12 @@ class FlowPlots2D(SliceData):
|
|
|
573
585
|
|
|
574
586
|
# loop over states:
|
|
575
587
|
for si, s in enumerate(states):
|
|
576
|
-
if animated and si
|
|
588
|
+
if animated and si == 0:
|
|
589
|
+
vmin = vmin if vmin is not None else np.min(data[..., vi])
|
|
590
|
+
vmax = vmax if vmax is not None else np.max(data[..., vi])
|
|
591
|
+
elif animated and si > 0:
|
|
577
592
|
add_bar = False
|
|
593
|
+
|
|
578
594
|
if not animated and title is None:
|
|
579
595
|
ttl = f"State {s}"
|
|
580
596
|
ttl += f", z = {int(np.round(z_pos))} m"
|
|
@@ -652,6 +668,7 @@ class FlowPlots2D(SliceData):
|
|
|
652
668
|
ret_im=False,
|
|
653
669
|
animated=False,
|
|
654
670
|
rotor_color=None,
|
|
671
|
+
precalc=False,
|
|
655
672
|
**kwargs,
|
|
656
673
|
):
|
|
657
674
|
"""
|
|
@@ -699,6 +716,11 @@ class FlowPlots2D(SliceData):
|
|
|
699
716
|
Switch for usage for an animation
|
|
700
717
|
rotor_color: str, optional
|
|
701
718
|
Indicate the rotor orientation by a colored line
|
|
719
|
+
precalc: bool or tuple
|
|
720
|
+
Flag for pre-calculation run, adding an additional
|
|
721
|
+
generator call before the actual plot generations,
|
|
722
|
+
yields data, states, gdata. The same tuple can be given
|
|
723
|
+
for avoiding its calculation and picking up from there.
|
|
702
724
|
kwargs: dict, optional
|
|
703
725
|
Additional parameters for SliceData.get_states_data_xz
|
|
704
726
|
|
|
@@ -718,16 +740,22 @@ class FlowPlots2D(SliceData):
|
|
|
718
740
|
wdi = variables.index(FV.WD)
|
|
719
741
|
wsi = variables.index(FV.WS)
|
|
720
742
|
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
743
|
+
if isinstance(precalc, (tuple, list)):
|
|
744
|
+
data, states, gdata = precalc
|
|
745
|
+
else:
|
|
746
|
+
data, states, gdata = self.get_states_data_xz(
|
|
747
|
+
variables=variables,
|
|
748
|
+
vmin={var: vmin} if vmin is not None else {},
|
|
749
|
+
vmax={var: vmax} if vmax is not None else {},
|
|
750
|
+
data_format="numpy",
|
|
751
|
+
ret_states=True,
|
|
752
|
+
ret_grid=True,
|
|
753
|
+
x_direction=x_direction,
|
|
754
|
+
**kwargs,
|
|
755
|
+
)
|
|
756
|
+
if precalc:
|
|
757
|
+
yield data, states, gdata
|
|
758
|
+
|
|
731
759
|
x_pos, y_pos, z_pos, __ = gdata
|
|
732
760
|
|
|
733
761
|
# define wind vector arrows:
|
|
@@ -826,6 +854,7 @@ class FlowPlots2D(SliceData):
|
|
|
826
854
|
ret_im=False,
|
|
827
855
|
animated=False,
|
|
828
856
|
rotor_color=None,
|
|
857
|
+
precalc=False,
|
|
829
858
|
**kwargs,
|
|
830
859
|
):
|
|
831
860
|
"""
|
|
@@ -873,6 +902,11 @@ class FlowPlots2D(SliceData):
|
|
|
873
902
|
Switch for usage for an animation
|
|
874
903
|
rotor_color: str, optional
|
|
875
904
|
Indicate the rotor orientation by a colored line
|
|
905
|
+
precalc: bool or tuple
|
|
906
|
+
Flag for pre-calculation run, adding an additional
|
|
907
|
+
generator call before the actual plot generations,
|
|
908
|
+
yields data, states, gdata. The same tuple can be given
|
|
909
|
+
for avoiding its calculation and picking up from there.
|
|
876
910
|
kwargs: dict, optional
|
|
877
911
|
Additional parameters for SliceData.get_states_data_yz
|
|
878
912
|
|
|
@@ -892,16 +926,22 @@ class FlowPlots2D(SliceData):
|
|
|
892
926
|
wdi = variables.index(FV.WD)
|
|
893
927
|
wsi = variables.index(FV.WS)
|
|
894
928
|
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
929
|
+
if isinstance(precalc, (tuple, list)):
|
|
930
|
+
data, states, gdata = precalc
|
|
931
|
+
else:
|
|
932
|
+
data, states, gdata = self.get_states_data_yz(
|
|
933
|
+
variables=variables,
|
|
934
|
+
vmin={var: vmin} if vmin is not None else {},
|
|
935
|
+
vmax={var: vmax} if vmax is not None else {},
|
|
936
|
+
data_format="numpy",
|
|
937
|
+
ret_states=True,
|
|
938
|
+
ret_grid=True,
|
|
939
|
+
x_direction=x_direction,
|
|
940
|
+
**kwargs,
|
|
941
|
+
)
|
|
942
|
+
if precalc:
|
|
943
|
+
yield data, states, gdata
|
|
944
|
+
|
|
905
945
|
x_pos, y_pos, z_pos, __ = gdata
|
|
906
946
|
|
|
907
947
|
# define wind vector arrows:
|
foxes/output/grids.py
CHANGED
|
@@ -12,7 +12,6 @@ def calc_point_results(
|
|
|
12
12
|
g_pts,
|
|
13
13
|
farm_results=None,
|
|
14
14
|
seq_iter=None,
|
|
15
|
-
runner=None,
|
|
16
15
|
verbosity=0,
|
|
17
16
|
**kwargs,
|
|
18
17
|
):
|
|
@@ -28,9 +27,7 @@ def calc_point_results(
|
|
|
28
27
|
farm_results: xarray.Dataset, optional
|
|
29
28
|
The farm results
|
|
30
29
|
seq_iter: foxes.algorithms.sequential.SequentialIter, optional
|
|
31
|
-
The sequential
|
|
32
|
-
runner: foxes.utils.runners.Runner, optional
|
|
33
|
-
The runner
|
|
30
|
+
The sequential iterator
|
|
34
31
|
verbosity: int
|
|
35
32
|
The verbosity level, 0 = silent
|
|
36
33
|
kwargs: dict, optional
|
|
@@ -41,11 +38,7 @@ def calc_point_results(
|
|
|
41
38
|
if averb is not None:
|
|
42
39
|
algo.verbosity = verbosity
|
|
43
40
|
fres = farm_results if seq_iter is None else seq_iter.farm_results
|
|
44
|
-
|
|
45
|
-
point_results = algo.calc_points(fres, points=g_pts, **kwargs)
|
|
46
|
-
else:
|
|
47
|
-
kwargs["points"] = g_pts
|
|
48
|
-
point_results = runner.run(algo.calc_points, args=(fres,), kwargs=kwargs)
|
|
41
|
+
point_results = algo.calc_points(fres, points=g_pts, **kwargs)
|
|
49
42
|
if averb is not None:
|
|
50
43
|
algo.verbosity = averb
|
|
51
44
|
|
|
@@ -54,7 +47,8 @@ def calc_point_results(
|
|
|
54
47
|
|
|
55
48
|
def get_grid_xy(
|
|
56
49
|
farm_results,
|
|
57
|
-
resolution,
|
|
50
|
+
resolution=None,
|
|
51
|
+
n_img_points=None,
|
|
58
52
|
xmin=None,
|
|
59
53
|
ymin=None,
|
|
60
54
|
xmax=None,
|
|
@@ -62,6 +56,8 @@ def get_grid_xy(
|
|
|
62
56
|
z=None,
|
|
63
57
|
xspace=500.0,
|
|
64
58
|
yspace=500.0,
|
|
59
|
+
states_sel=None,
|
|
60
|
+
states_isel=None,
|
|
65
61
|
verbosity=0,
|
|
66
62
|
):
|
|
67
63
|
"""
|
|
@@ -74,6 +70,8 @@ def get_grid_xy(
|
|
|
74
70
|
dimensions (state, turbine)
|
|
75
71
|
resolution: float
|
|
76
72
|
The resolution in m
|
|
73
|
+
n_img_points: tuple of int, optional
|
|
74
|
+
The number of image points (n, m) in the two directions
|
|
77
75
|
xmin: float
|
|
78
76
|
The min x coordinate, or None for automatic
|
|
79
77
|
ymin: float
|
|
@@ -88,6 +86,10 @@ def get_grid_xy(
|
|
|
88
86
|
The extra space in x direction, before and after wind farm
|
|
89
87
|
yspace: float
|
|
90
88
|
The extra space in y direction, before and after wind farm
|
|
89
|
+
states_sel: list, optional
|
|
90
|
+
Reduce to selected states
|
|
91
|
+
states_isel: list, optional
|
|
92
|
+
Reduce to the selected states indices
|
|
91
93
|
verbosity: int, optional
|
|
92
94
|
The verbosity level
|
|
93
95
|
|
|
@@ -103,8 +105,11 @@ def get_grid_xy(
|
|
|
103
105
|
The grid points, shape: (n_states, n_pts, 3)
|
|
104
106
|
|
|
105
107
|
"""
|
|
106
|
-
|
|
107
108
|
# prepare:
|
|
109
|
+
if states_isel is not None:
|
|
110
|
+
farm_results = farm_results.isel({FC.STATE: states_isel})
|
|
111
|
+
if states_sel is not None:
|
|
112
|
+
farm_results = farm_results.sel({FC.STATE: states_sel})
|
|
108
113
|
n_states = farm_results[FV.H].shape[0]
|
|
109
114
|
|
|
110
115
|
# get base rectangle:
|
|
@@ -115,10 +120,22 @@ def get_grid_xy(
|
|
|
115
120
|
y_max = ymax if ymax is not None else farm_results[FV.Y].max().to_numpy() + yspace
|
|
116
121
|
z_max = z if z is not None else farm_results[FV.H].max().to_numpy()
|
|
117
122
|
|
|
123
|
+
# compute number of points:
|
|
124
|
+
if resolution is not None and n_img_points is None:
|
|
125
|
+
nx = int((x_max - x_min) / resolution + 0.5) + 1
|
|
126
|
+
ny = int((y_max - y_min) / resolution + 0.5) + 1
|
|
127
|
+
elif resolution is None and n_img_points is not None:
|
|
128
|
+
nx, ny = n_img_points
|
|
129
|
+
else:
|
|
130
|
+
raise ValueError(
|
|
131
|
+
f"Expecting either 'resolution' or 'n_img_points', got: resolution = {resolution}, n_img_points = {n_img_points}"
|
|
132
|
+
)
|
|
133
|
+
|
|
134
|
+
# compute points:
|
|
118
135
|
x_pos, x_res = np.linspace(
|
|
119
136
|
x_min,
|
|
120
137
|
x_max,
|
|
121
|
-
num=
|
|
138
|
+
num=nx,
|
|
122
139
|
endpoint=True,
|
|
123
140
|
retstep=True,
|
|
124
141
|
dtype=None,
|
|
@@ -126,7 +143,7 @@ def get_grid_xy(
|
|
|
126
143
|
y_pos, y_res = np.linspace(
|
|
127
144
|
y_min,
|
|
128
145
|
y_max,
|
|
129
|
-
num=
|
|
146
|
+
num=ny,
|
|
130
147
|
endpoint=True,
|
|
131
148
|
retstep=True,
|
|
132
149
|
dtype=None,
|
|
@@ -158,7 +175,8 @@ def get_grid_xy(
|
|
|
158
175
|
|
|
159
176
|
def get_grid_xz(
|
|
160
177
|
farm_results,
|
|
161
|
-
resolution,
|
|
178
|
+
resolution=None,
|
|
179
|
+
n_img_points=None,
|
|
162
180
|
x_direction=270,
|
|
163
181
|
xmin=None,
|
|
164
182
|
zmin=0.0,
|
|
@@ -167,6 +185,8 @@ def get_grid_xz(
|
|
|
167
185
|
y=None,
|
|
168
186
|
xspace=500.0,
|
|
169
187
|
zspace=500.0,
|
|
188
|
+
states_sel=None,
|
|
189
|
+
states_isel=None,
|
|
170
190
|
verbosity=0,
|
|
171
191
|
):
|
|
172
192
|
"""
|
|
@@ -177,8 +197,10 @@ def get_grid_xz(
|
|
|
177
197
|
farm_results: xarray.Dataset
|
|
178
198
|
The farm results. The calculated variables have
|
|
179
199
|
dimensions (state, turbine)
|
|
180
|
-
resolution: float
|
|
200
|
+
resolution: float, optional
|
|
181
201
|
The resolution in m
|
|
202
|
+
n_img_points: tuple of int, optional
|
|
203
|
+
The number of image points (n, m) in the two directions
|
|
182
204
|
x_direction: float
|
|
183
205
|
The direction of the x axis, 0 = north
|
|
184
206
|
xmin: float
|
|
@@ -195,6 +217,10 @@ def get_grid_xz(
|
|
|
195
217
|
The extra space in x direction, before and after wind farm
|
|
196
218
|
zspace: float
|
|
197
219
|
The extra space in z direction, below and above wind farm
|
|
220
|
+
states_sel: list, optional
|
|
221
|
+
Reduce to selected states
|
|
222
|
+
states_isel: list, optional
|
|
223
|
+
Reduce to the selected states indices
|
|
198
224
|
verbosity: int, optional
|
|
199
225
|
The verbosity level
|
|
200
226
|
|
|
@@ -212,6 +238,10 @@ def get_grid_xz(
|
|
|
212
238
|
"""
|
|
213
239
|
|
|
214
240
|
# prepare:
|
|
241
|
+
if states_isel is not None:
|
|
242
|
+
farm_results = farm_results.isel({FC.STATE: states_isel})
|
|
243
|
+
if states_sel is not None:
|
|
244
|
+
farm_results = farm_results.sel({FC.STATE: states_sel})
|
|
215
245
|
n_states, n_turbines = farm_results[FV.H].shape
|
|
216
246
|
n_x = np.append(wd2uv(x_direction), [0.0], axis=0)
|
|
217
247
|
n_z = np.array([0.0, 0.0, 1.0])
|
|
@@ -236,10 +266,22 @@ def get_grid_xz(
|
|
|
236
266
|
y_max = y if y is not None else np.max(yy)
|
|
237
267
|
del xx, yy, zz
|
|
238
268
|
|
|
269
|
+
# compute number of points:
|
|
270
|
+
if resolution is not None and n_img_points is None:
|
|
271
|
+
nx = int((x_max - x_min) / resolution + 0.5) + 1
|
|
272
|
+
nz = int((z_max - z_min) / resolution + 0.5) + 1
|
|
273
|
+
elif resolution is None and n_img_points is not None:
|
|
274
|
+
nx, nz = n_img_points
|
|
275
|
+
else:
|
|
276
|
+
raise ValueError(
|
|
277
|
+
f"Expecting either 'resolution' or 'n_img_points', got: resolution = {resolution}, n_img_points = {n_img_points}"
|
|
278
|
+
)
|
|
279
|
+
|
|
280
|
+
# compute points:
|
|
239
281
|
x_pos, x_res = np.linspace(
|
|
240
282
|
x_min,
|
|
241
283
|
x_max,
|
|
242
|
-
num=
|
|
284
|
+
num=nx,
|
|
243
285
|
endpoint=True,
|
|
244
286
|
retstep=True,
|
|
245
287
|
dtype=None,
|
|
@@ -247,7 +289,7 @@ def get_grid_xz(
|
|
|
247
289
|
z_pos, z_res = np.linspace(
|
|
248
290
|
z_min,
|
|
249
291
|
z_max,
|
|
250
|
-
num=
|
|
292
|
+
num=nz,
|
|
251
293
|
endpoint=True,
|
|
252
294
|
retstep=True,
|
|
253
295
|
dtype=None,
|
|
@@ -279,7 +321,8 @@ def get_grid_xz(
|
|
|
279
321
|
|
|
280
322
|
def get_grid_yz(
|
|
281
323
|
farm_results,
|
|
282
|
-
resolution,
|
|
324
|
+
resolution=None,
|
|
325
|
+
n_img_points=None,
|
|
283
326
|
x_direction=270,
|
|
284
327
|
ymin=None,
|
|
285
328
|
zmin=0.0,
|
|
@@ -288,6 +331,8 @@ def get_grid_yz(
|
|
|
288
331
|
x=None,
|
|
289
332
|
yspace=500.0,
|
|
290
333
|
zspace=500.0,
|
|
334
|
+
states_sel=None,
|
|
335
|
+
states_isel=None,
|
|
291
336
|
verbosity=0,
|
|
292
337
|
):
|
|
293
338
|
"""
|
|
@@ -298,8 +343,10 @@ def get_grid_yz(
|
|
|
298
343
|
farm_results: xarray.Dataset
|
|
299
344
|
The farm results. The calculated variables have
|
|
300
345
|
dimensions (state, turbine)
|
|
301
|
-
resolution: float
|
|
346
|
+
resolution: float, optional
|
|
302
347
|
The resolution in m
|
|
348
|
+
n_img_points: tuple of int, optional
|
|
349
|
+
The number of image points (n, m) in the two directions
|
|
303
350
|
x_direction: float
|
|
304
351
|
The direction of the x axis, 0 = north
|
|
305
352
|
ymin: float
|
|
@@ -316,6 +363,10 @@ def get_grid_yz(
|
|
|
316
363
|
The extra space in y direction, before and after wind farm
|
|
317
364
|
zspace: float
|
|
318
365
|
The extra space in z direction, below and above wind farm
|
|
366
|
+
states_sel: list, optional
|
|
367
|
+
Reduce to selected states
|
|
368
|
+
states_isel: list, optional
|
|
369
|
+
Reduce to the selected states indices
|
|
319
370
|
verbosity: int, optional
|
|
320
371
|
The verbosity level
|
|
321
372
|
|
|
@@ -333,6 +384,10 @@ def get_grid_yz(
|
|
|
333
384
|
"""
|
|
334
385
|
|
|
335
386
|
# prepare:
|
|
387
|
+
if states_isel is not None:
|
|
388
|
+
farm_results = farm_results.isel({FC.STATE: states_isel})
|
|
389
|
+
if states_sel is not None:
|
|
390
|
+
farm_results = farm_results.sel({FC.STATE: states_sel})
|
|
336
391
|
n_states, n_turbines = farm_results[FV.H].shape
|
|
337
392
|
n_x = np.append(wd2uv(x_direction), [0.0], axis=0)
|
|
338
393
|
n_z = np.array([0.0, 0.0, 1.0])
|
|
@@ -357,10 +412,22 @@ def get_grid_yz(
|
|
|
357
412
|
x_max = x if x is not None else np.max(xx)
|
|
358
413
|
del xx, yy, zz
|
|
359
414
|
|
|
415
|
+
# compute number of points:
|
|
416
|
+
if resolution is not None and n_img_points is None:
|
|
417
|
+
ny = int((y_max - y_min) / resolution + 0.5) + 1
|
|
418
|
+
nz = int((z_max - z_min) / resolution + 0.5) + 1
|
|
419
|
+
elif resolution is None and n_img_points is not None:
|
|
420
|
+
ny, nz = n_img_points
|
|
421
|
+
else:
|
|
422
|
+
raise ValueError(
|
|
423
|
+
f"Expecting either 'resolution' or 'n_img_points', got: resolution = {resolution}, n_img_points = {n_img_points}"
|
|
424
|
+
)
|
|
425
|
+
|
|
426
|
+
# compute points:
|
|
360
427
|
y_pos, y_res = np.linspace(
|
|
361
428
|
y_min,
|
|
362
429
|
y_max,
|
|
363
|
-
num=
|
|
430
|
+
num=ny,
|
|
364
431
|
endpoint=True,
|
|
365
432
|
retstep=True,
|
|
366
433
|
dtype=None,
|
|
@@ -368,7 +435,7 @@ def get_grid_yz(
|
|
|
368
435
|
z_pos, z_res = np.linspace(
|
|
369
436
|
z_min,
|
|
370
437
|
z_max,
|
|
371
|
-
num=
|
|
438
|
+
num=nz,
|
|
372
439
|
endpoint=True,
|
|
373
440
|
retstep=True,
|
|
374
441
|
dtype=None,
|
|
@@ -614,7 +681,10 @@ def np2xr_sp(data, states, a_pos, b_pos, c_pos, ori, label_map={}):
|
|
|
614
681
|
return Dataset(
|
|
615
682
|
coords={s: states, b: b_pos, a: a_pos},
|
|
616
683
|
data_vars={
|
|
617
|
-
v
|
|
684
|
+
label_map.get(v, v): (
|
|
685
|
+
(s, b, a),
|
|
686
|
+
np.swapaxes(d.reshape(n_s, n_a, n_b), 1, 2),
|
|
687
|
+
)
|
|
618
688
|
for v, d in data.items()
|
|
619
689
|
},
|
|
620
690
|
attrs={c: float(c_pos)},
|
foxes/output/results_writer.py
CHANGED
|
@@ -83,7 +83,7 @@ class ResultsWriter(Output):
|
|
|
83
83
|
Parameters
|
|
84
84
|
----------
|
|
85
85
|
file_path: str
|
|
86
|
-
Path
|
|
86
|
+
Path for the csv file
|
|
87
87
|
variables: dict or list of str, optional
|
|
88
88
|
The variables to be written. If a dict, then
|
|
89
89
|
the keys are the foxes variables and the values
|
|
@@ -150,7 +150,7 @@ class ResultsWriter(Output):
|
|
|
150
150
|
Parameters
|
|
151
151
|
----------
|
|
152
152
|
file_path: str
|
|
153
|
-
Path
|
|
153
|
+
Path for the nc file
|
|
154
154
|
variables: dict or list of str, optional
|
|
155
155
|
The variables to be written. If a dict, then
|
|
156
156
|
the keys are the foxes variables and the values
|
foxes/output/rose_plot.py
CHANGED
|
@@ -118,7 +118,7 @@ class RosePlotOutput(Output):
|
|
|
118
118
|
var: str
|
|
119
119
|
The data variable name
|
|
120
120
|
var_bins: list of float
|
|
121
|
-
The variable bin
|
|
121
|
+
The variable bin separation values
|
|
122
122
|
wd_var: str, optional
|
|
123
123
|
The wind direction variable name
|
|
124
124
|
turbine: int, optional
|
|
@@ -231,7 +231,7 @@ class RosePlotOutput(Output):
|
|
|
231
231
|
var: str
|
|
232
232
|
The data variable name
|
|
233
233
|
var_bins: list of float
|
|
234
|
-
The variable bin
|
|
234
|
+
The variable bin separation values
|
|
235
235
|
wd_var: str, optional
|
|
236
236
|
The wind direction variable name
|
|
237
237
|
turbine: int, optional
|
|
@@ -330,7 +330,7 @@ class RosePlotOutput(Output):
|
|
|
330
330
|
var: str
|
|
331
331
|
The data variable name
|
|
332
332
|
var_bins: list of float
|
|
333
|
-
The variable bin
|
|
333
|
+
The variable bin separation values
|
|
334
334
|
ret_data: bool
|
|
335
335
|
Flag for returning wind rose data
|
|
336
336
|
kwargs: dict, optional
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
+
from copy import deepcopy
|
|
2
|
+
|
|
1
3
|
from foxes.algorithms.sequential import SequentialPlugin
|
|
2
4
|
|
|
3
|
-
from .flow_plots import FlowPlots2D
|
|
5
|
+
from ..flow_plots_2d.flow_plots import FlowPlots2D
|
|
4
6
|
|
|
5
7
|
|
|
6
8
|
class SeqFlowAnimationPlugin(SequentialPlugin):
|
|
@@ -12,16 +14,14 @@ class SeqFlowAnimationPlugin(SequentialPlugin):
|
|
|
12
14
|
----------
|
|
13
15
|
orientation: str
|
|
14
16
|
The orientation, either "yx", "xz" or "yz"
|
|
15
|
-
runner: foxes.utils.runners.Runner
|
|
16
|
-
The runner
|
|
17
17
|
pars: dict
|
|
18
18
|
Additional parameters for plotting
|
|
19
19
|
|
|
20
|
-
:group: output.
|
|
20
|
+
:group: output.seq_plugins
|
|
21
21
|
|
|
22
22
|
"""
|
|
23
23
|
|
|
24
|
-
def __init__(self, orientation,
|
|
24
|
+
def __init__(self, orientation, **pars):
|
|
25
25
|
"""
|
|
26
26
|
Constructor.
|
|
27
27
|
|
|
@@ -29,15 +29,12 @@ class SeqFlowAnimationPlugin(SequentialPlugin):
|
|
|
29
29
|
----------
|
|
30
30
|
orientation: str
|
|
31
31
|
The orientation, either "yx", "xz" or "yz"
|
|
32
|
-
runner: foxes.utils.runners.Runner, optional
|
|
33
|
-
The runner
|
|
34
32
|
pars: dict, optional
|
|
35
33
|
Additional parameters for plotting
|
|
36
34
|
|
|
37
35
|
"""
|
|
38
36
|
super().__init__()
|
|
39
37
|
self.orientation = orientation
|
|
40
|
-
self.runner = runner
|
|
41
38
|
self.pars = pars
|
|
42
39
|
|
|
43
40
|
if "title" in self.pars and callable(self.pars["title"]):
|
|
@@ -52,7 +49,7 @@ class SeqFlowAnimationPlugin(SequentialPlugin):
|
|
|
52
49
|
Parameters
|
|
53
50
|
----------
|
|
54
51
|
algo: foxes.algorithms.sequential.Sequential
|
|
55
|
-
The current
|
|
52
|
+
The current sequential algorithm
|
|
56
53
|
|
|
57
54
|
"""
|
|
58
55
|
super().initialize(algo)
|
|
@@ -65,7 +62,7 @@ class SeqFlowAnimationPlugin(SequentialPlugin):
|
|
|
65
62
|
Parameters
|
|
66
63
|
----------
|
|
67
64
|
algo: foxes.algorithms.sequential.Sequential
|
|
68
|
-
The latest
|
|
65
|
+
The latest sequential algorithm
|
|
69
66
|
fres: xarray.Dataset
|
|
70
67
|
The latest farm results
|
|
71
68
|
pres: xarray.Dataset, optional
|
|
@@ -74,28 +71,73 @@ class SeqFlowAnimationPlugin(SequentialPlugin):
|
|
|
74
71
|
"""
|
|
75
72
|
super().update(algo, fres, pres)
|
|
76
73
|
|
|
77
|
-
o = FlowPlots2D(algo, fres
|
|
74
|
+
o = FlowPlots2D(algo, fres)
|
|
78
75
|
|
|
79
76
|
if self._tfun is not None:
|
|
80
77
|
self.pars["title"] = self._tfun(algo.states.counter, algo.states.index()[0])
|
|
81
78
|
|
|
82
79
|
if self.orientation == "xy":
|
|
83
|
-
|
|
80
|
+
d = next(o.gen_states_fig_xy(**self.pars, precalc=True))
|
|
84
81
|
elif self.orientation == "xz":
|
|
85
|
-
|
|
82
|
+
d = next(o.gen_states_fig_xz(**self.pars, precalc=True))
|
|
86
83
|
elif self.orientation == "yz":
|
|
87
|
-
|
|
84
|
+
d = next(o.gen_states_fig_yz(**self.pars, precalc=True))
|
|
88
85
|
else:
|
|
89
86
|
raise KeyError(
|
|
90
87
|
f"Unkown orientation '{self.orientation}', choises: xy, xz, yz"
|
|
91
88
|
)
|
|
92
89
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
90
|
+
# minimize stored data:
|
|
91
|
+
od = [d[0], d[1], None]
|
|
92
|
+
if len(self._data) == 0:
|
|
93
|
+
od[2] = d[2]
|
|
94
|
+
of = (
|
|
95
|
+
fres
|
|
96
|
+
if ("rotor_color" in self.pars and self.pars["rotor_color"] is not None)
|
|
97
|
+
else None
|
|
98
|
+
)
|
|
99
|
+
|
|
100
|
+
self._data.append((of, od))
|
|
101
|
+
|
|
102
|
+
def gen_images(self, ax):
|
|
103
|
+
"""
|
|
104
|
+
|
|
105
|
+
Parameters
|
|
106
|
+
----------
|
|
107
|
+
ax: matplotlib.Axis
|
|
108
|
+
The plotting axis
|
|
109
|
+
|
|
110
|
+
Yields
|
|
111
|
+
------
|
|
112
|
+
imgs: tuple
|
|
113
|
+
The (figure, artists) tuple
|
|
114
|
+
|
|
115
|
+
"""
|
|
116
|
+
fig = ax.get_figure()
|
|
117
|
+
gdata = None
|
|
118
|
+
while len(self._data):
|
|
119
|
+
|
|
120
|
+
fres, d = self._data.pop(0)
|
|
121
|
+
|
|
122
|
+
if d[2] is not None:
|
|
123
|
+
gdata = d[2]
|
|
124
|
+
|
|
125
|
+
o = FlowPlots2D(self.algo, fres)
|
|
126
|
+
|
|
127
|
+
yield next(
|
|
128
|
+
o.gen_states_fig_xy(
|
|
129
|
+
**self.pars,
|
|
130
|
+
ax=ax,
|
|
131
|
+
fig=fig,
|
|
132
|
+
ret_im=True,
|
|
133
|
+
precalc=(d[0], d[1], gdata),
|
|
134
|
+
)
|
|
135
|
+
)
|
|
136
|
+
|
|
137
|
+
del o, fres, d
|
|
98
138
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
139
|
+
if (
|
|
140
|
+
self.pars.get("vmin", None) is not None
|
|
141
|
+
and self.pars.get("vmax", None) is not None
|
|
142
|
+
):
|
|
143
|
+
self.pars["add_bar"] = False
|