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.

Files changed (190) hide show
  1. docs/source/conf.py +3 -3
  2. examples/abl_states/run.py +2 -2
  3. examples/compare_rotors_pwakes/run.py +1 -1
  4. examples/compare_wakes/run.py +1 -2
  5. examples/dyn_wakes/run.py +29 -6
  6. examples/induction/run.py +3 -3
  7. examples/multi_height/run.py +1 -1
  8. examples/power_mask/run.py +2 -2
  9. examples/quickstart/run.py +0 -1
  10. examples/random_timeseries/run.py +3 -4
  11. examples/scan_row/run.py +3 -3
  12. examples/sequential/run.py +33 -10
  13. examples/single_state/run.py +3 -4
  14. examples/states_lookup_table/run.py +3 -3
  15. examples/streamline_wakes/run.py +27 -4
  16. examples/tab_file/run.py +3 -3
  17. examples/timelines/run.py +29 -5
  18. examples/timeseries/run.py +3 -3
  19. examples/timeseries_slurm/run.py +3 -3
  20. examples/wind_rose/run.py +3 -3
  21. examples/yawed_wake/run.py +16 -8
  22. foxes/__init__.py +21 -17
  23. foxes/algorithms/__init__.py +6 -6
  24. foxes/algorithms/downwind/__init__.py +2 -2
  25. foxes/algorithms/downwind/downwind.py +44 -12
  26. foxes/algorithms/downwind/models/__init__.py +6 -6
  27. foxes/algorithms/downwind/models/farm_wakes_calc.py +11 -9
  28. foxes/algorithms/downwind/models/init_farm_data.py +0 -1
  29. foxes/algorithms/downwind/models/point_wakes_calc.py +7 -13
  30. foxes/algorithms/downwind/models/set_amb_point_results.py +6 -6
  31. foxes/algorithms/iterative/__init__.py +7 -3
  32. foxes/algorithms/iterative/iterative.py +1 -2
  33. foxes/algorithms/iterative/models/__init__.py +7 -3
  34. foxes/algorithms/iterative/models/farm_wakes_calc.py +9 -5
  35. foxes/algorithms/sequential/__init__.py +3 -3
  36. foxes/algorithms/sequential/models/__init__.py +2 -2
  37. foxes/algorithms/sequential/sequential.py +3 -4
  38. foxes/config/__init__.py +5 -1
  39. foxes/constants.py +16 -0
  40. foxes/core/__init__.py +45 -22
  41. foxes/core/algorithm.py +0 -1
  42. foxes/core/data.py +19 -18
  43. foxes/core/engine.py +9 -13
  44. foxes/core/farm_controller.py +2 -2
  45. foxes/core/ground_model.py +4 -13
  46. foxes/core/model.py +5 -5
  47. foxes/core/partial_wakes_model.py +147 -10
  48. foxes/core/point_data_model.py +2 -3
  49. foxes/core/rotor_model.py +3 -3
  50. foxes/core/states.py +2 -3
  51. foxes/core/turbine.py +2 -1
  52. foxes/core/wake_deflection.py +130 -0
  53. foxes/core/wake_model.py +222 -9
  54. foxes/core/wake_superposition.py +122 -4
  55. foxes/core/wind_farm.py +6 -6
  56. foxes/data/__init__.py +7 -2
  57. foxes/data/states/weibull_sectors_12.csv +13 -0
  58. foxes/data/states/weibull_sectors_12.nc +0 -0
  59. foxes/engines/__init__.py +14 -15
  60. foxes/engines/dask.py +39 -14
  61. foxes/engines/numpy.py +0 -3
  62. foxes/input/__init__.py +3 -3
  63. foxes/input/farm_layout/__init__.py +8 -8
  64. foxes/input/farm_layout/from_csv.py +1 -1
  65. foxes/input/farm_layout/ring.py +0 -1
  66. foxes/input/states/__init__.py +22 -12
  67. foxes/input/states/create/__init__.py +3 -2
  68. foxes/input/states/field_data_nc.py +10 -24
  69. foxes/input/states/multi_height.py +9 -6
  70. foxes/input/states/one_point_flow.py +0 -4
  71. foxes/input/states/single.py +1 -1
  72. foxes/input/states/states_table.py +10 -7
  73. foxes/input/states/weibull_sectors.py +225 -0
  74. foxes/input/states/wrg_states.py +7 -5
  75. foxes/input/yaml/__init__.py +9 -3
  76. foxes/input/yaml/dict.py +19 -19
  77. foxes/input/yaml/windio/__init__.py +10 -5
  78. foxes/input/yaml/windio/read_attributes.py +2 -2
  79. foxes/input/yaml/windio/read_farm.py +5 -5
  80. foxes/input/yaml/windio/read_fields.py +4 -2
  81. foxes/input/yaml/windio/read_site.py +52 -0
  82. foxes/input/yaml/windio/windio.py +1 -1
  83. foxes/models/__init__.py +15 -14
  84. foxes/models/axial_induction/__init__.py +2 -2
  85. foxes/models/farm_controllers/__init__.py +1 -1
  86. foxes/models/farm_models/__init__.py +1 -1
  87. foxes/models/ground_models/__init__.py +3 -2
  88. foxes/models/ground_models/wake_mirror.py +3 -3
  89. foxes/models/model_book.py +175 -49
  90. foxes/models/partial_wakes/__init__.py +6 -6
  91. foxes/models/partial_wakes/axiwake.py +30 -5
  92. foxes/models/partial_wakes/centre.py +47 -0
  93. foxes/models/partial_wakes/rotor_points.py +41 -11
  94. foxes/models/partial_wakes/segregated.py +2 -25
  95. foxes/models/partial_wakes/top_hat.py +27 -2
  96. foxes/models/point_models/__init__.py +4 -4
  97. foxes/models/rotor_models/__init__.py +3 -3
  98. foxes/models/turbine_models/__init__.py +11 -11
  99. foxes/models/turbine_models/set_farm_vars.py +0 -1
  100. foxes/models/turbine_types/PCt_file.py +0 -2
  101. foxes/models/turbine_types/PCt_from_two.py +0 -2
  102. foxes/models/turbine_types/__init__.py +9 -9
  103. foxes/models/vertical_profiles/__init__.py +7 -7
  104. foxes/models/wake_deflections/__init__.py +3 -0
  105. foxes/models/{wake_frames/yawed_wakes.py → wake_deflections/bastankhah2016.py} +32 -111
  106. foxes/models/wake_deflections/jimenez.py +277 -0
  107. foxes/models/wake_deflections/no_deflection.py +94 -0
  108. foxes/models/wake_frames/__init__.py +6 -7
  109. foxes/models/wake_frames/dynamic_wakes.py +12 -3
  110. foxes/models/wake_frames/rotor_wd.py +3 -1
  111. foxes/models/wake_frames/seq_dynamic_wakes.py +41 -7
  112. foxes/models/wake_frames/streamlines.py +8 -6
  113. foxes/models/wake_frames/timelines.py +9 -3
  114. foxes/models/wake_models/__init__.py +7 -7
  115. foxes/models/wake_models/dist_sliced.py +50 -84
  116. foxes/models/wake_models/gaussian.py +20 -0
  117. foxes/models/wake_models/induction/__init__.py +5 -5
  118. foxes/models/wake_models/induction/rankine_half_body.py +30 -71
  119. foxes/models/wake_models/induction/rathmann.py +65 -64
  120. foxes/models/wake_models/induction/self_similar.py +65 -68
  121. foxes/models/wake_models/induction/self_similar2020.py +0 -3
  122. foxes/models/wake_models/induction/vortex_sheet.py +71 -75
  123. foxes/models/wake_models/ti/__init__.py +2 -2
  124. foxes/models/wake_models/ti/crespo_hernandez.py +5 -3
  125. foxes/models/wake_models/ti/iec_ti.py +6 -4
  126. foxes/models/wake_models/top_hat.py +58 -7
  127. foxes/models/wake_models/wind/__init__.py +6 -4
  128. foxes/models/wake_models/wind/bastankhah14.py +25 -7
  129. foxes/models/wake_models/wind/bastankhah16.py +35 -3
  130. foxes/models/wake_models/wind/jensen.py +15 -2
  131. foxes/models/wake_models/wind/turbopark.py +28 -2
  132. foxes/models/wake_superpositions/__init__.py +18 -9
  133. foxes/models/wake_superpositions/ti_linear.py +4 -4
  134. foxes/models/wake_superpositions/ti_max.py +4 -4
  135. foxes/models/wake_superpositions/ti_pow.py +4 -4
  136. foxes/models/wake_superpositions/ti_quadratic.py +4 -4
  137. foxes/models/wake_superpositions/wind_vector.py +257 -0
  138. foxes/models/wake_superpositions/ws_linear.py +9 -10
  139. foxes/models/wake_superpositions/ws_max.py +8 -8
  140. foxes/models/wake_superpositions/ws_pow.py +8 -8
  141. foxes/models/wake_superpositions/ws_product.py +4 -4
  142. foxes/models/wake_superpositions/ws_quadratic.py +8 -8
  143. foxes/output/__init__.py +21 -19
  144. foxes/output/farm_layout.py +2 -2
  145. foxes/output/farm_results_eval.py +15 -15
  146. foxes/output/flow_plots_2d/__init__.py +2 -2
  147. foxes/output/flow_plots_2d/get_fig.py +4 -2
  148. foxes/output/rose_plot.py +3 -3
  149. foxes/output/seq_plugins/__init__.py +2 -2
  150. foxes/output/seq_plugins/seq_flow_ani_plugin.py +0 -3
  151. foxes/output/seq_plugins/seq_wake_debug_plugin.py +0 -1
  152. foxes/output/turbine_type_curves.py +7 -8
  153. foxes/utils/__init__.py +37 -19
  154. foxes/utils/abl/__init__.py +4 -4
  155. foxes/utils/cubic_roots.py +1 -1
  156. foxes/utils/data_book.py +4 -3
  157. foxes/utils/dict.py +3 -3
  158. foxes/utils/exec_python.py +5 -5
  159. foxes/utils/factory.py +1 -3
  160. foxes/utils/geom2d/__init__.py +7 -5
  161. foxes/utils/geopandas_utils.py +2 -2
  162. foxes/utils/pandas_utils.py +4 -3
  163. foxes/utils/tab_files.py +0 -1
  164. foxes/utils/weibull.py +28 -0
  165. foxes/utils/wrg_utils.py +3 -1
  166. foxes/utils/xarray_utils.py +9 -2
  167. foxes/variables.py +67 -9
  168. {foxes-1.3.dist-info → foxes-1.4.dist-info}/METADATA +6 -15
  169. foxes-1.4.dist-info/RECORD +320 -0
  170. {foxes-1.3.dist-info → foxes-1.4.dist-info}/WHEEL +1 -1
  171. tests/1_verification/flappy_0_6/PCt_files/flappy/run.py +2 -3
  172. tests/1_verification/flappy_0_6/PCt_files/test_PCt_files.py +1 -1
  173. tests/1_verification/flappy_0_6/abl_states/flappy/run.py +0 -1
  174. tests/1_verification/flappy_0_6/partial_top_hat/flappy/run.py +0 -1
  175. tests/1_verification/flappy_0_6/partial_top_hat/test_partial_top_hat.py +0 -2
  176. tests/1_verification/flappy_0_6/row_Jensen_linear_centre/test_row_Jensen_linear_centre.py +0 -1
  177. tests/1_verification/flappy_0_6/row_Jensen_linear_tophat/test_row_Jensen_linear_tophat.py +0 -1
  178. tests/1_verification/flappy_0_6/row_Jensen_linear_tophat_IECTI2005/test_row_Jensen_linear_tophat_IECTI_2005.py +0 -1
  179. tests/1_verification/flappy_0_6/row_Jensen_linear_tophat_IECTI2019/test_row_Jensen_linear_tophat_IECTI_2019.py +0 -1
  180. tests/1_verification/flappy_0_6/row_Jensen_quadratic_centre/test_row_Jensen_quadratic_centre.py +0 -1
  181. tests/1_verification/flappy_0_6_2/grid_rotors/flappy/run.py +0 -2
  182. tests/1_verification/flappy_0_6_2/row_Bastankhah_Crespo/test_row_Bastankhah_Crespo.py +0 -1
  183. tests/1_verification/flappy_0_6_2/row_Bastankhah_linear_centre/flappy/run.py +0 -1
  184. tests/1_verification/flappy_0_6_2/row_Bastankhah_linear_centre/test_row_Bastankhah_linear_centre.py +0 -1
  185. foxes/output/round.py +0 -10
  186. foxes/utils/pandas_helpers.py +0 -178
  187. foxes-1.3.dist-info/RECORD +0 -313
  188. {foxes-1.3.dist-info → foxes-1.4.dist-info}/entry_points.txt +0 -0
  189. {foxes-1.3.dist-info → foxes-1.4.dist-info/licenses}/LICENSE +0 -0
  190. {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 .round import round_defaults
6
- from .output import Output
7
- from .farm_layout import FarmLayoutOutput
8
- from .farm_results_eval import FarmResultsEval
9
- from .rose_plot import RosePlotOutput, StatesRosePlotOutput, WindRoseBinPlot
10
- from .results_writer import ResultsWriter
11
- from .state_turbine_map import StateTurbineMap
12
- from .turbine_type_curves import TurbineTypeCurves
13
- from .animation import Animator
14
- from .calc_points import PointCalculator
15
- from .slice_data import SliceData
16
- from .slices_data import SlicesData
17
- from .rotor_point_plots import RotorPointPlot
18
- from .state_turbine_table import StateTurbineTable
19
- from .plt import plt
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, SeqWakeDebugPlugin
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
@@ -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(f"Missing farm_results for switch from_results.")
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(f"Please specify results_state for switch from_results.")
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 == 0
71
- ), f"Found {nns} nan values for variable '{v}' of shape {vdata.shape}"
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 == 0
147
- ), f"Found {nns} nan values for variable '{v}' of shape {vdata.shape}"
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 == 0
196
- ), f"Found {nns} nan values for variable '{v}' of shape {vdata.shape}"
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 == 0
249
- ), f"Found {nns} nan values for variable '{v}' of shape {vdata.shape}"
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 == True:
474
+ elif hours is None and annual:
475
475
  duration_hours = 8760
476
476
  elif hours is None:
477
477
  raise ValueError(
478
- f"Expecting parameter 'hours' for non-timeseries data, or 'annual=True'"
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(f"State")
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(f"Require either farm_results or point_results")
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})" for i in range(n_wsb - 1, -1, -1)
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:
@@ -109,7 +109,6 @@ class SeqWakeDebugPlugin(SequentialPlugin):
109
109
 
110
110
  """
111
111
  while len(self._data):
112
-
113
112
  dt, pts, v = self._data.pop(0)
114
113
 
115
114
  N = len(pts)
@@ -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
- l = "Wind speed [m/s]" if x_label is None else x_label
186
- ax.set_xlabel(l)
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
- l = f"Power [kW]"
189
+ lb = "Power [kW]"
191
190
  elif v == FV.CT:
192
- l = "ct [-]"
191
+ lb = "ct [-]"
193
192
  else:
194
- l = v
193
+ lb = v
195
194
  else:
196
- l = y_labels[i]
197
- ax.set_ylabel(l)
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, wd2wdvec, wdvec2wd, uv2wd, delta_wd
6
- from .pandas_utils import PandasFileHelper
7
- from .xarray_utils import write_nc
8
- from .subclasses import all_subclasses, new_cls, new_instance
9
- from .dict import Dict
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 two_circles
23
- from . import abl
24
- from . import geom2d
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
@@ -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
@@ -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 = lambda f: any(
70
- [len(f) > len(s) and f[-len(s) :] == s for s in file_sfx]
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) == 1
82
- ), f"Expecting a single default entry, got {len(deflt)}"
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]
@@ -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 indicator in a:
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
 
@@ -2,8 +2,10 @@
2
2
  Geometries in two dimensions.
3
3
  """
4
4
 
5
- from .area_geometry import AreaGeometry, InvertedAreaGeometry
6
- from .area_geometry import AreaUnion, AreaIntersection
7
- from .polygon import ClosedPolygon
8
- from .circle import Circle
9
- from .half_plane import HalfPlane
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
@@ -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 == True:
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 name in pnames:
193
+ if name not in pnames:
194
194
  raise KeyError(
195
195
  f"Name '{name}' not found in file '{fname}'. Names: {pnames}"
196
196
  )
@@ -106,9 +106,10 @@ class PandasFileHelper:
106
106
  elif sfx == "h5":
107
107
  f = pd.read_hdf
108
108
  elif sfx == "nc":
109
- f = lambda fname, **pars: xarray.open_dataset(
110
- fname, **pars
111
- ).to_dataframe()
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
@@ -63,7 +63,6 @@ def read_tab_file(fname, normalize=True):
63
63
 
64
64
 
65
65
  if __name__ == "__main__":
66
-
67
66
  import argparse
68
67
 
69
68
  parser = argparse.ArgumentParser()
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)))