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.

Files changed (215) hide show
  1. docs/source/conf.py +353 -0
  2. examples/abl_states/run.py +160 -0
  3. examples/compare_rotors_pwakes/run.py +217 -0
  4. examples/compare_wakes/run.py +241 -0
  5. examples/dyn_wakes/run.py +311 -0
  6. examples/field_data_nc/run.py +121 -0
  7. examples/induction/run.py +201 -0
  8. examples/multi_height/run.py +113 -0
  9. examples/power_mask/run.py +249 -0
  10. examples/random_timeseries/run.py +210 -0
  11. examples/scan_row/run.py +193 -0
  12. examples/sector_management/run.py +162 -0
  13. examples/sequential/run.py +209 -0
  14. examples/single_state/run.py +201 -0
  15. examples/states_lookup_table/run.py +137 -0
  16. examples/streamline_wakes/run.py +138 -0
  17. examples/tab_file/run.py +142 -0
  18. examples/timelines/run.py +267 -0
  19. examples/timeseries/run.py +190 -0
  20. examples/timeseries_slurm/run.py +185 -0
  21. examples/wind_rose/run.py +141 -0
  22. examples/windio/run.py +29 -0
  23. examples/yawed_wake/run.py +196 -0
  24. foxes/__init__.py +4 -8
  25. foxes/algorithms/__init__.py +1 -1
  26. foxes/algorithms/downwind/downwind.py +247 -111
  27. foxes/algorithms/downwind/models/farm_wakes_calc.py +12 -7
  28. foxes/algorithms/downwind/models/init_farm_data.py +2 -2
  29. foxes/algorithms/downwind/models/point_wakes_calc.py +6 -7
  30. foxes/algorithms/downwind/models/reorder_farm_output.py +1 -2
  31. foxes/algorithms/downwind/models/set_amb_farm_results.py +1 -1
  32. foxes/algorithms/downwind/models/set_amb_point_results.py +5 -3
  33. foxes/algorithms/iterative/iterative.py +74 -34
  34. foxes/algorithms/iterative/models/farm_wakes_calc.py +12 -7
  35. foxes/algorithms/iterative/models/urelax.py +3 -3
  36. foxes/algorithms/sequential/models/plugin.py +5 -5
  37. foxes/algorithms/sequential/models/seq_state.py +1 -1
  38. foxes/algorithms/sequential/sequential.py +126 -255
  39. foxes/constants.py +22 -7
  40. foxes/core/__init__.py +1 -0
  41. foxes/core/algorithm.py +632 -147
  42. foxes/core/data.py +252 -20
  43. foxes/core/data_calc_model.py +15 -291
  44. foxes/core/engine.py +640 -0
  45. foxes/core/farm_controller.py +38 -10
  46. foxes/core/farm_data_model.py +16 -1
  47. foxes/core/ground_model.py +2 -2
  48. foxes/core/model.py +249 -182
  49. foxes/core/partial_wakes_model.py +1 -1
  50. foxes/core/point_data_model.py +17 -2
  51. foxes/core/rotor_model.py +27 -21
  52. foxes/core/states.py +17 -1
  53. foxes/core/turbine_type.py +28 -0
  54. foxes/core/wake_frame.py +30 -34
  55. foxes/core/wake_model.py +5 -5
  56. foxes/core/wake_superposition.py +1 -1
  57. foxes/data/windio/windio_5turbines_timeseries.yaml +31 -15
  58. foxes/engines/__init__.py +17 -0
  59. foxes/engines/dask.py +982 -0
  60. foxes/engines/default.py +75 -0
  61. foxes/engines/futures.py +72 -0
  62. foxes/engines/mpi.py +38 -0
  63. foxes/engines/multiprocess.py +71 -0
  64. foxes/engines/numpy.py +167 -0
  65. foxes/engines/pool.py +249 -0
  66. foxes/engines/ray.py +79 -0
  67. foxes/engines/single.py +141 -0
  68. foxes/input/farm_layout/__init__.py +1 -0
  69. foxes/input/farm_layout/from_csv.py +4 -0
  70. foxes/input/farm_layout/from_json.py +2 -2
  71. foxes/input/farm_layout/grid.py +2 -2
  72. foxes/input/farm_layout/ring.py +65 -0
  73. foxes/input/farm_layout/row.py +2 -2
  74. foxes/input/states/__init__.py +7 -0
  75. foxes/input/states/create/random_abl_states.py +1 -1
  76. foxes/input/states/field_data_nc.py +158 -33
  77. foxes/input/states/multi_height.py +128 -14
  78. foxes/input/states/one_point_flow.py +577 -0
  79. foxes/input/states/scan_ws.py +74 -3
  80. foxes/input/states/single.py +1 -1
  81. foxes/input/states/slice_data_nc.py +681 -0
  82. foxes/input/states/states_table.py +204 -35
  83. foxes/input/windio/__init__.py +2 -2
  84. foxes/input/windio/get_states.py +44 -23
  85. foxes/input/windio/read_attributes.py +48 -17
  86. foxes/input/windio/read_farm.py +116 -102
  87. foxes/input/windio/read_fields.py +16 -6
  88. foxes/input/windio/read_outputs.py +71 -24
  89. foxes/input/windio/runner.py +31 -17
  90. foxes/input/windio/windio.py +41 -23
  91. foxes/models/farm_models/turbine2farm.py +1 -1
  92. foxes/models/ground_models/wake_mirror.py +10 -6
  93. foxes/models/model_book.py +58 -20
  94. foxes/models/partial_wakes/axiwake.py +3 -3
  95. foxes/models/partial_wakes/rotor_points.py +3 -3
  96. foxes/models/partial_wakes/top_hat.py +2 -2
  97. foxes/models/point_models/set_uniform_data.py +1 -1
  98. foxes/models/point_models/tke2ti.py +1 -1
  99. foxes/models/point_models/wake_deltas.py +1 -1
  100. foxes/models/rotor_models/centre.py +4 -0
  101. foxes/models/rotor_models/grid.py +24 -25
  102. foxes/models/rotor_models/levels.py +4 -5
  103. foxes/models/turbine_models/calculator.py +4 -6
  104. foxes/models/turbine_models/kTI_model.py +22 -6
  105. foxes/models/turbine_models/lookup_table.py +30 -4
  106. foxes/models/turbine_models/rotor_centre_calc.py +4 -3
  107. foxes/models/turbine_models/set_farm_vars.py +103 -34
  108. foxes/models/turbine_types/PCt_file.py +27 -3
  109. foxes/models/turbine_types/PCt_from_two.py +27 -3
  110. foxes/models/turbine_types/TBL_file.py +80 -0
  111. foxes/models/turbine_types/__init__.py +2 -0
  112. foxes/models/turbine_types/lookup.py +316 -0
  113. foxes/models/turbine_types/null_type.py +51 -1
  114. foxes/models/turbine_types/wsrho2PCt_from_two.py +29 -5
  115. foxes/models/turbine_types/wsti2PCt_from_two.py +31 -7
  116. foxes/models/vertical_profiles/__init__.py +1 -1
  117. foxes/models/vertical_profiles/data_profile.py +1 -1
  118. foxes/models/wake_frames/__init__.py +1 -0
  119. foxes/models/wake_frames/dynamic_wakes.py +424 -0
  120. foxes/models/wake_frames/farm_order.py +25 -5
  121. foxes/models/wake_frames/rotor_wd.py +6 -4
  122. foxes/models/wake_frames/seq_dynamic_wakes.py +61 -74
  123. foxes/models/wake_frames/streamlines.py +21 -22
  124. foxes/models/wake_frames/timelines.py +330 -129
  125. foxes/models/wake_frames/yawed_wakes.py +7 -4
  126. foxes/models/wake_models/dist_sliced.py +2 -4
  127. foxes/models/wake_models/induction/rankine_half_body.py +5 -5
  128. foxes/models/wake_models/induction/rathmann.py +78 -24
  129. foxes/models/wake_models/induction/self_similar.py +78 -28
  130. foxes/models/wake_models/induction/vortex_sheet.py +86 -48
  131. foxes/models/wake_models/ti/crespo_hernandez.py +6 -4
  132. foxes/models/wake_models/ti/iec_ti.py +40 -21
  133. foxes/models/wake_models/top_hat.py +1 -1
  134. foxes/models/wake_models/wind/bastankhah14.py +8 -6
  135. foxes/models/wake_models/wind/bastankhah16.py +17 -16
  136. foxes/models/wake_models/wind/jensen.py +4 -3
  137. foxes/models/wake_models/wind/turbopark.py +16 -13
  138. foxes/models/wake_superpositions/ti_linear.py +1 -1
  139. foxes/models/wake_superpositions/ti_max.py +1 -1
  140. foxes/models/wake_superpositions/ti_pow.py +1 -1
  141. foxes/models/wake_superpositions/ti_quadratic.py +1 -1
  142. foxes/models/wake_superpositions/ws_linear.py +8 -7
  143. foxes/models/wake_superpositions/ws_max.py +8 -7
  144. foxes/models/wake_superpositions/ws_pow.py +8 -7
  145. foxes/models/wake_superpositions/ws_product.py +5 -5
  146. foxes/models/wake_superpositions/ws_quadratic.py +8 -7
  147. foxes/output/__init__.py +4 -1
  148. foxes/output/farm_layout.py +16 -12
  149. foxes/output/farm_results_eval.py +1 -1
  150. foxes/output/flow_plots_2d/__init__.py +0 -1
  151. foxes/output/flow_plots_2d/flow_plots.py +70 -30
  152. foxes/output/grids.py +92 -22
  153. foxes/output/results_writer.py +2 -2
  154. foxes/output/rose_plot.py +3 -3
  155. foxes/output/seq_plugins/__init__.py +2 -0
  156. foxes/output/{flow_plots_2d → seq_plugins}/seq_flow_ani_plugin.py +64 -22
  157. foxes/output/seq_plugins/seq_wake_debug_plugin.py +145 -0
  158. foxes/output/slice_data.py +131 -111
  159. foxes/output/state_turbine_map.py +19 -14
  160. foxes/output/state_turbine_table.py +19 -19
  161. foxes/utils/__init__.py +1 -1
  162. foxes/utils/abl/neutral.py +2 -2
  163. foxes/utils/abl/stable.py +2 -2
  164. foxes/utils/abl/unstable.py +2 -2
  165. foxes/utils/data_book.py +1 -1
  166. foxes/utils/dev_utils.py +42 -0
  167. foxes/utils/dict.py +24 -1
  168. foxes/utils/exec_python.py +1 -1
  169. foxes/utils/factory.py +176 -53
  170. foxes/utils/geom2d/circle.py +1 -1
  171. foxes/utils/geom2d/polygon.py +1 -1
  172. foxes/utils/geopandas_utils.py +2 -2
  173. foxes/utils/load.py +2 -2
  174. foxes/utils/pandas_helpers.py +3 -2
  175. foxes/utils/wind_dir.py +0 -2
  176. foxes/utils/xarray_utils.py +24 -14
  177. foxes/variables.py +39 -2
  178. {foxes-0.8.2.dist-info → foxes-1.1.0.2.dist-info}/METADATA +75 -33
  179. foxes-1.1.0.2.dist-info/RECORD +309 -0
  180. {foxes-0.8.2.dist-info → foxes-1.1.0.2.dist-info}/WHEEL +1 -1
  181. foxes-1.1.0.2.dist-info/top_level.txt +4 -0
  182. tests/0_consistency/iterative/test_iterative.py +92 -0
  183. tests/0_consistency/partial_wakes/test_partial_wakes.py +90 -0
  184. tests/1_verification/flappy_0_6/PCt_files/flappy/run.py +85 -0
  185. tests/1_verification/flappy_0_6/PCt_files/test_PCt_files.py +103 -0
  186. tests/1_verification/flappy_0_6/abl_states/flappy/run.py +85 -0
  187. tests/1_verification/flappy_0_6/abl_states/test_abl_states.py +87 -0
  188. tests/1_verification/flappy_0_6/partial_top_hat/flappy/run.py +82 -0
  189. tests/1_verification/flappy_0_6/partial_top_hat/test_partial_top_hat.py +82 -0
  190. tests/1_verification/flappy_0_6/row_Jensen_linear_centre/flappy/run.py +92 -0
  191. tests/1_verification/flappy_0_6/row_Jensen_linear_centre/test_row_Jensen_linear_centre.py +93 -0
  192. tests/1_verification/flappy_0_6/row_Jensen_linear_tophat/flappy/run.py +92 -0
  193. tests/1_verification/flappy_0_6/row_Jensen_linear_tophat/test_row_Jensen_linear_tophat.py +96 -0
  194. tests/1_verification/flappy_0_6/row_Jensen_linear_tophat_IECTI2005/flappy/run.py +94 -0
  195. tests/1_verification/flappy_0_6/row_Jensen_linear_tophat_IECTI2005/test_row_Jensen_linear_tophat_IECTI_2005.py +122 -0
  196. tests/1_verification/flappy_0_6/row_Jensen_linear_tophat_IECTI2019/flappy/run.py +94 -0
  197. tests/1_verification/flappy_0_6/row_Jensen_linear_tophat_IECTI2019/test_row_Jensen_linear_tophat_IECTI_2019.py +122 -0
  198. tests/1_verification/flappy_0_6/row_Jensen_quadratic_centre/flappy/run.py +92 -0
  199. tests/1_verification/flappy_0_6/row_Jensen_quadratic_centre/test_row_Jensen_quadratic_centre.py +93 -0
  200. tests/1_verification/flappy_0_6_2/grid_rotors/flappy/run.py +85 -0
  201. tests/1_verification/flappy_0_6_2/grid_rotors/test_grid_rotors.py +130 -0
  202. tests/1_verification/flappy_0_6_2/row_Bastankhah_Crespo/flappy/run.py +96 -0
  203. tests/1_verification/flappy_0_6_2/row_Bastankhah_Crespo/test_row_Bastankhah_Crespo.py +116 -0
  204. tests/1_verification/flappy_0_6_2/row_Bastankhah_linear_centre/flappy/run.py +93 -0
  205. tests/1_verification/flappy_0_6_2/row_Bastankhah_linear_centre/test_row_Bastankhah_linear_centre.py +99 -0
  206. tests/3_examples/test_examples.py +34 -0
  207. foxes/VERSION +0 -1
  208. foxes/output/flow_plots_2d.py +0 -0
  209. foxes/utils/geopandas_helpers.py +0 -294
  210. foxes/utils/runners/__init__.py +0 -1
  211. foxes/utils/runners/runners.py +0 -280
  212. foxes-0.8.2.dist-info/RECORD +0 -247
  213. foxes-0.8.2.dist-info/top_level.txt +0 -1
  214. foxes-0.8.2.dist-info/zip-safe +0 -1
  215. {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
- data, states, gdata = self.get_states_data_xy(
550
- variables=variables,
551
- vmin={var: vmin} if vmin is not None else {},
552
- vmax={var: vmax} if vmax is not None else {},
553
- data_format="numpy",
554
- ret_states=True,
555
- ret_grid=True,
556
- **kwargs,
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 > 0 and vmin is not None and vmax is not None:
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
- data, states, gdata = self.get_states_data_xz(
722
- variables=variables,
723
- vmin={var: vmin} if vmin is not None else {},
724
- vmax={var: vmax} if vmax is not None else {},
725
- data_format="numpy",
726
- ret_states=True,
727
- ret_grid=True,
728
- x_direction=x_direction,
729
- **kwargs,
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
- data, states, gdata = self.get_states_data_yz(
896
- variables=variables,
897
- vmin={var: vmin} if vmin is not None else {},
898
- vmax={var: vmax} if vmax is not None else {},
899
- data_format="numpy",
900
- ret_states=True,
901
- ret_grid=True,
902
- x_direction=x_direction,
903
- **kwargs,
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 itarator
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
- if runner is None:
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=int((x_max - x_min) / resolution) + 1,
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=int((y_max - y_min) / resolution) + 1,
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=int((x_max - x_min) / resolution) + 1,
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=int((z_max - z_min) / resolution) + 1,
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=int((y_max - y_min) / resolution) + 1,
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=int((z_max - z_min) / resolution) + 1,
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: ((s, b, a), np.swapaxes(d.reshape(n_s, n_a, n_b), 1, 2))
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)},
@@ -83,7 +83,7 @@ class ResultsWriter(Output):
83
83
  Parameters
84
84
  ----------
85
85
  file_path: str
86
- Path the the csv file
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 the the csv file
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 seperation values
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 seperation values
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 seperation values
333
+ The variable bin separation values
334
334
  ret_data: bool
335
335
  Flag for returning wind rose data
336
336
  kwargs: dict, optional
@@ -0,0 +1,2 @@
1
+ from .seq_flow_ani_plugin import SeqFlowAnimationPlugin
2
+ from .seq_wake_debug_plugin import SeqWakeDebugPlugin
@@ -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.flow_plots_2d
20
+ :group: output.seq_plugins
21
21
 
22
22
  """
23
23
 
24
- def __init__(self, orientation, runner=None, **pars):
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 sequetial algorithm
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 sequetial algorithm
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, self.runner)
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
- self._data.append(next(o.gen_states_fig_xy(**self.pars)))
80
+ d = next(o.gen_states_fig_xy(**self.pars, precalc=True))
84
81
  elif self.orientation == "xz":
85
- self._data.append(next(o.gen_states_fig_xz(**self.pars)))
82
+ d = next(o.gen_states_fig_xz(**self.pars, precalc=True))
86
83
  elif self.orientation == "yz":
87
- self._data.append(next(o.gen_states_fig_yz(**self.pars)))
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
- if (
94
- self.pars.get("vmin", None) is not None
95
- and self.pars.get("vmax", None) is not None
96
- ):
97
- self.pars["add_bar"] = False
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
- def gen_images(self):
100
- for d in self._data:
101
- yield d
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