foxes 0.8.1__py3-none-any.whl → 1.0__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 (175) 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_RHB/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 +183 -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 +232 -101
  27. foxes/algorithms/downwind/models/farm_wakes_calc.py +11 -6
  28. foxes/algorithms/downwind/models/init_farm_data.py +1 -1
  29. foxes/algorithms/downwind/models/point_wakes_calc.py +5 -6
  30. foxes/algorithms/downwind/models/reorder_farm_output.py +0 -1
  31. foxes/algorithms/downwind/models/set_amb_point_results.py +4 -2
  32. foxes/algorithms/iterative/iterative.py +73 -33
  33. foxes/algorithms/iterative/models/farm_wakes_calc.py +11 -6
  34. foxes/algorithms/sequential/models/plugin.py +1 -1
  35. foxes/algorithms/sequential/sequential.py +126 -255
  36. foxes/constants.py +17 -2
  37. foxes/core/__init__.py +1 -0
  38. foxes/core/algorithm.py +631 -146
  39. foxes/core/data.py +252 -20
  40. foxes/core/data_calc_model.py +13 -289
  41. foxes/core/engine.py +630 -0
  42. foxes/core/farm_controller.py +37 -9
  43. foxes/core/farm_data_model.py +15 -0
  44. foxes/core/model.py +133 -80
  45. foxes/core/point_data_model.py +15 -0
  46. foxes/core/rotor_model.py +27 -21
  47. foxes/core/states.py +16 -0
  48. foxes/core/turbine_type.py +28 -0
  49. foxes/core/wake_frame.py +22 -4
  50. foxes/core/wake_model.py +2 -3
  51. foxes/data/windio/windio_5turbines_timeseries.yaml +23 -1
  52. foxes/engines/__init__.py +16 -0
  53. foxes/engines/dask.py +975 -0
  54. foxes/engines/default.py +75 -0
  55. foxes/engines/futures.py +72 -0
  56. foxes/engines/mpi.py +38 -0
  57. foxes/engines/multiprocess.py +74 -0
  58. foxes/engines/numpy.py +185 -0
  59. foxes/engines/pool.py +263 -0
  60. foxes/engines/single.py +139 -0
  61. foxes/input/farm_layout/__init__.py +1 -0
  62. foxes/input/farm_layout/from_csv.py +4 -0
  63. foxes/input/farm_layout/from_json.py +1 -1
  64. foxes/input/farm_layout/grid.py +2 -2
  65. foxes/input/farm_layout/ring.py +65 -0
  66. foxes/input/farm_layout/row.py +2 -2
  67. foxes/input/states/__init__.py +6 -0
  68. foxes/input/states/create/random_abl_states.py +1 -1
  69. foxes/input/states/field_data_nc.py +157 -32
  70. foxes/input/states/multi_height.py +127 -13
  71. foxes/input/states/one_point_flow.py +577 -0
  72. foxes/input/states/scan_ws.py +73 -2
  73. foxes/input/states/states_table.py +204 -35
  74. foxes/input/windio/__init__.py +1 -1
  75. foxes/input/windio/get_states.py +44 -23
  76. foxes/input/windio/read_attributes.py +41 -16
  77. foxes/input/windio/read_farm.py +116 -102
  78. foxes/input/windio/read_fields.py +13 -6
  79. foxes/input/windio/read_outputs.py +63 -22
  80. foxes/input/windio/runner.py +31 -17
  81. foxes/input/windio/windio.py +36 -22
  82. foxes/models/ground_models/wake_mirror.py +8 -4
  83. foxes/models/model_book.py +29 -18
  84. foxes/models/partial_wakes/rotor_points.py +3 -3
  85. foxes/models/rotor_models/centre.py +4 -0
  86. foxes/models/rotor_models/grid.py +22 -23
  87. foxes/models/rotor_models/levels.py +4 -5
  88. foxes/models/turbine_models/calculator.py +0 -2
  89. foxes/models/turbine_models/lookup_table.py +27 -2
  90. foxes/models/turbine_models/rotor_centre_calc.py +4 -3
  91. foxes/models/turbine_models/set_farm_vars.py +103 -34
  92. foxes/models/turbine_types/PCt_file.py +24 -0
  93. foxes/models/turbine_types/PCt_from_two.py +24 -0
  94. foxes/models/turbine_types/__init__.py +1 -0
  95. foxes/models/turbine_types/lookup.py +316 -0
  96. foxes/models/turbine_types/null_type.py +50 -0
  97. foxes/models/turbine_types/wsrho2PCt_from_two.py +24 -0
  98. foxes/models/turbine_types/wsti2PCt_from_two.py +24 -0
  99. foxes/models/vertical_profiles/data_profile.py +1 -1
  100. foxes/models/wake_frames/__init__.py +1 -0
  101. foxes/models/wake_frames/dynamic_wakes.py +424 -0
  102. foxes/models/wake_frames/farm_order.py +23 -3
  103. foxes/models/wake_frames/rotor_wd.py +4 -2
  104. foxes/models/wake_frames/seq_dynamic_wakes.py +56 -63
  105. foxes/models/wake_frames/streamlines.py +19 -20
  106. foxes/models/wake_frames/timelines.py +328 -127
  107. foxes/models/wake_frames/yawed_wakes.py +4 -1
  108. foxes/models/wake_models/dist_sliced.py +1 -3
  109. foxes/models/wake_models/induction/rankine_half_body.py +4 -4
  110. foxes/models/wake_models/induction/rathmann.py +2 -2
  111. foxes/models/wake_models/induction/self_similar.py +2 -2
  112. foxes/models/wake_models/induction/vortex_sheet.py +2 -2
  113. foxes/models/wake_models/ti/iec_ti.py +34 -17
  114. foxes/models/wake_models/top_hat.py +1 -1
  115. foxes/models/wake_models/wind/bastankhah14.py +2 -2
  116. foxes/models/wake_models/wind/bastankhah16.py +8 -7
  117. foxes/models/wake_models/wind/jensen.py +1 -1
  118. foxes/models/wake_models/wind/turbopark.py +2 -2
  119. foxes/output/__init__.py +4 -1
  120. foxes/output/farm_layout.py +2 -2
  121. foxes/output/flow_plots_2d/__init__.py +0 -1
  122. foxes/output/flow_plots_2d/flow_plots.py +70 -30
  123. foxes/output/grids.py +91 -21
  124. foxes/output/seq_plugins/__init__.py +2 -0
  125. foxes/output/{flow_plots_2d → seq_plugins}/seq_flow_ani_plugin.py +62 -20
  126. foxes/output/seq_plugins/seq_wake_debug_plugin.py +145 -0
  127. foxes/output/slice_data.py +131 -111
  128. foxes/output/state_turbine_map.py +18 -13
  129. foxes/output/state_turbine_table.py +19 -19
  130. foxes/utils/__init__.py +1 -1
  131. foxes/utils/dev_utils.py +42 -0
  132. foxes/utils/dict.py +1 -1
  133. foxes/utils/factory.py +147 -52
  134. foxes/utils/pandas_helpers.py +4 -3
  135. foxes/utils/wind_dir.py +0 -2
  136. foxes/utils/xarray_utils.py +25 -13
  137. foxes/variables.py +37 -0
  138. {foxes-0.8.1.dist-info → foxes-1.0.dist-info}/METADATA +72 -34
  139. foxes-1.0.dist-info/RECORD +307 -0
  140. {foxes-0.8.1.dist-info → foxes-1.0.dist-info}/WHEEL +1 -1
  141. foxes-1.0.dist-info/top_level.txt +4 -0
  142. tests/0_consistency/iterative/test_iterative.py +92 -0
  143. tests/0_consistency/partial_wakes/test_partial_wakes.py +90 -0
  144. tests/1_verification/flappy_0_6/PCt_files/flappy/run.py +85 -0
  145. tests/1_verification/flappy_0_6/PCt_files/test_PCt_files.py +103 -0
  146. tests/1_verification/flappy_0_6/abl_states/flappy/run.py +85 -0
  147. tests/1_verification/flappy_0_6/abl_states/test_abl_states.py +87 -0
  148. tests/1_verification/flappy_0_6/partial_top_hat/flappy/run.py +82 -0
  149. tests/1_verification/flappy_0_6/partial_top_hat/test_partial_top_hat.py +82 -0
  150. tests/1_verification/flappy_0_6/row_Jensen_linear_centre/flappy/run.py +92 -0
  151. tests/1_verification/flappy_0_6/row_Jensen_linear_centre/test_row_Jensen_linear_centre.py +93 -0
  152. tests/1_verification/flappy_0_6/row_Jensen_linear_tophat/flappy/run.py +92 -0
  153. tests/1_verification/flappy_0_6/row_Jensen_linear_tophat/test_row_Jensen_linear_tophat.py +96 -0
  154. tests/1_verification/flappy_0_6/row_Jensen_linear_tophat_IECTI2005/flappy/run.py +94 -0
  155. tests/1_verification/flappy_0_6/row_Jensen_linear_tophat_IECTI2005/test_row_Jensen_linear_tophat_IECTI_2005.py +122 -0
  156. tests/1_verification/flappy_0_6/row_Jensen_linear_tophat_IECTI2019/flappy/run.py +94 -0
  157. tests/1_verification/flappy_0_6/row_Jensen_linear_tophat_IECTI2019/test_row_Jensen_linear_tophat_IECTI_2019.py +122 -0
  158. tests/1_verification/flappy_0_6/row_Jensen_quadratic_centre/flappy/run.py +92 -0
  159. tests/1_verification/flappy_0_6/row_Jensen_quadratic_centre/test_row_Jensen_quadratic_centre.py +93 -0
  160. tests/1_verification/flappy_0_6_2/grid_rotors/flappy/run.py +85 -0
  161. tests/1_verification/flappy_0_6_2/grid_rotors/test_grid_rotors.py +130 -0
  162. tests/1_verification/flappy_0_6_2/row_Bastankhah_Crespo/flappy/run.py +96 -0
  163. tests/1_verification/flappy_0_6_2/row_Bastankhah_Crespo/test_row_Bastankhah_Crespo.py +116 -0
  164. tests/1_verification/flappy_0_6_2/row_Bastankhah_linear_centre/flappy/run.py +93 -0
  165. tests/1_verification/flappy_0_6_2/row_Bastankhah_linear_centre/test_row_Bastankhah_linear_centre.py +99 -0
  166. tests/3_examples/test_examples.py +34 -0
  167. foxes/VERSION +0 -1
  168. foxes/output/flow_plots_2d.py +0 -0
  169. foxes/utils/plotly_helpers.py +0 -19
  170. foxes/utils/runners/__init__.py +0 -1
  171. foxes/utils/runners/runners.py +0 -280
  172. foxes-0.8.1.dist-info/RECORD +0 -248
  173. foxes-0.8.1.dist-info/top_level.txt +0 -1
  174. foxes-0.8.1.dist-info/zip-safe +0 -1
  175. {foxes-0.8.1.dist-info → foxes-1.0.dist-info}/LICENSE +0 -0
@@ -1,7 +1,7 @@
1
1
  import numpy as np
2
2
 
3
3
  from foxes.core import TurbineInductionModel
4
- from foxes.utils import uv2wd, wd2uv
4
+ from foxes.utils import uv2wd, wd2uv, delta_wd
5
5
  import foxes.variables as FV
6
6
  import foxes.constants as FC
7
7
 
@@ -198,7 +198,7 @@ class RankineHalfBody(TurbineInductionModel):
198
198
  xs = -np.sqrt(m / (4 * ws + 1e-15))
199
199
 
200
200
  # set values out of body shape
201
- st_sel = (ct > 0) & ((RHB_shape < -1) | (x < xs))
201
+ st_sel = (ct > 1e-8) & ((RHB_shape < -1) | (x < xs))
202
202
  if np.any(st_sel):
203
203
  # apply selection
204
204
  xyz = wake_coos[st_sel]
@@ -209,7 +209,7 @@ class RankineHalfBody(TurbineInductionModel):
209
209
  wake_deltas["V"][st_sel] += vel_factor * xyz[:, 1]
210
210
 
211
211
  # set values inside body shape
212
- st_sel = (ct > 0) & (RHB_shape >= -1) & (x >= xs) & (x <= 0)
212
+ st_sel = (ct > 1e-8) & (RHB_shape >= -1) & (x >= xs) & (x <= 0)
213
213
  if np.any(st_sel):
214
214
  # apply selection
215
215
  xyz = np.zeros_like(wake_coos[st_sel])
@@ -270,4 +270,4 @@ class RankineHalfBody(TurbineInductionModel):
270
270
  new_wd = uv2wd(wind_vec)
271
271
  new_ws = np.linalg.norm(wind_vec, axis=-1)
272
272
  wake_deltas[FV.WS] += new_ws - amb_results[FV.WS]
273
- wake_deltas[FV.WD] += new_wd - amb_results[FV.WD]
273
+ wake_deltas[FV.WD] += delta_wd(amb_results[FV.WD], new_wd)
@@ -199,7 +199,7 @@ class Rathmann(TurbineInductionModel):
199
199
  return sin_alpha * sin_beta * (1 + x_R**2)
200
200
 
201
201
  # ws delta in front of rotor
202
- sp_sel = (ct > 0) & (x_R <= 0)
202
+ sp_sel = (ct > 1e-8) & (x_R <= 0)
203
203
  if np.any(sp_sel):
204
204
  xr = x_R[sp_sel]
205
205
  a = self.induction.ct2a(ct[sp_sel])
@@ -209,7 +209,7 @@ class Rathmann(TurbineInductionModel):
209
209
  # ws delta behind rotor
210
210
  if not self.pre_rotor_only:
211
211
  # mirror -blockage in rotor plane
212
- sp_sel = (ct > 0) & (x_R > 0) & (r_R > 1)
212
+ sp_sel = (ct > 1e-8) & (x_R > 0) & (r_R > 1)
213
213
  if np.any(sp_sel):
214
214
  xr = x_R[sp_sel]
215
215
  a = self.induction.ct2a(ct[sp_sel])
@@ -214,7 +214,7 @@ class SelfSimilar(TurbineInductionModel):
214
214
  r_R = np.linalg.norm(wake_coos[..., 1:3], axis=-1) / R
215
215
 
216
216
  # select values
217
- sp_sel = (ct > 0) & (x_R <= 0) # upstream
217
+ sp_sel = (ct > 1e-8) & (x_R <= 0) # upstream
218
218
  if np.any(sp_sel):
219
219
  # velocity eqn 10 from [1]
220
220
  xr = x_R[sp_sel]
@@ -225,7 +225,7 @@ class SelfSimilar(TurbineInductionModel):
225
225
 
226
226
  # set area behind to mirrored value EXCEPT for area behind turbine
227
227
  if not self.pre_rotor_only:
228
- sp_sel = (ct > 0) & (x_R > 0) & (r_R > 1)
228
+ sp_sel = (ct > 1e-8) & (x_R > 0) & (r_R > 1)
229
229
  if np.any(sp_sel):
230
230
  # velocity eqn 10 from [1]
231
231
  xr = x_R[sp_sel]
@@ -183,7 +183,7 @@ class VortexSheet(TurbineInductionModel):
183
183
  downwind_index=downwind_index,
184
184
  )
185
185
 
186
- sp_sel = (ct > 0) & (x <= 0)
186
+ sp_sel = (ct > 1e-8) & (x <= 0)
187
187
  ws_sel = ws[sp_sel]
188
188
  ct_sel = ct[sp_sel]
189
189
  r_sph_sel = r_sph[sp_sel]
@@ -203,7 +203,7 @@ class VortexSheet(TurbineInductionModel):
203
203
 
204
204
  if not self.pre_rotor_only:
205
205
  sp_sel = (
206
- (ct > 0) & (x > 0) & (r > D / 2)
206
+ (ct > 1e-8) & (x > 0) & (r > D / 2)
207
207
  ) # mirror in rotor plane and inverse blockage, but not directly behind rotor
208
208
  ws_sel = ws[sp_sel]
209
209
  ct_sel = ct[sp_sel]
@@ -54,24 +54,27 @@ class IECTIWake(TopHatWakeModel):
54
54
 
55
55
  """
56
56
  super().__init__(superpositions={FV.TI: superposition}, induction=induction)
57
+ self.iec_type = iec_type
58
+ self.wake_k = None
57
59
 
58
- if opening_angle is not None:
60
+ if opening_angle is None:
61
+ self.wake_k = WakeK(**wake_k)
62
+ else:
59
63
  if "k" in wake_k or "ka" in wake_k or "kb" in wake_k:
60
64
  raise KeyError(
61
65
  f"Can handle 'opening_angle' or ('k', 'ka', 'kb') parameters, not both"
62
66
  )
63
- wake_k["k"] = float(np.tan(np.deg2rad(opening_angle / 2.0)))
64
-
65
- self.iec_type = iec_type
66
- self.wake_k = WakeK(**wake_k)
67
+ self._k = float(np.tan(np.deg2rad(opening_angle / 2.0)))
67
68
 
68
69
  def __repr__(self):
69
70
  iname = (
70
71
  self.induction if isinstance(self.induction, str) else self.induction.name
71
72
  )
72
73
  s = f"{type(self).__name__}"
73
- s += f"({self.superpositions[FV.TI]}, induction={iname}, "
74
- s += self.wake_k.repr() + ")"
74
+ s += f"({self.superpositions[FV.TI]}, induction={iname}"
75
+ if self.wake_k is not None:
76
+ s += ", " + self.wake_k.repr()
77
+ s += ")"
75
78
  return s
76
79
 
77
80
  def sub_models(self):
@@ -84,7 +87,7 @@ class IECTIWake(TopHatWakeModel):
84
87
  All sub models
85
88
 
86
89
  """
87
- return [self.wake_k]
90
+ return [self.wake_k] if self.wake_k is not None else []
88
91
 
89
92
  def new_wake_deltas(self, algo, mdata, fdata, tdata):
90
93
  """
@@ -147,15 +150,29 @@ class IECTIWake(TopHatWakeModel):
147
150
  The wake radii, shape: (n_states, n_targets)
148
151
 
149
152
  """
150
- k = self.wake_k(
151
- FC.STATE_TARGET,
152
- algo=algo,
153
- fdata=fdata,
154
- tdata=tdata,
155
- upcast=False,
156
- downwind_index=downwind_index,
157
- )
158
- return k * x
153
+ if self.wake_k is None:
154
+ return self._k * x
155
+ else:
156
+ D = self.get_data(
157
+ FV.D,
158
+ FC.STATE_TARGET,
159
+ lookup="w",
160
+ algo=algo,
161
+ fdata=fdata,
162
+ tdata=tdata,
163
+ downwind_index=downwind_index,
164
+ upcast=True,
165
+ )
166
+
167
+ k = self.wake_k(
168
+ FC.STATE_TARGET,
169
+ algo=algo,
170
+ fdata=fdata,
171
+ tdata=tdata,
172
+ upcast=True,
173
+ downwind_index=downwind_index,
174
+ )
175
+ return D / 2 + k * x
159
176
 
160
177
  def calc_centreline(
161
178
  self,
@@ -209,7 +209,7 @@ class TopHatWakeModel(AxisymmetricWakeModel):
209
209
  wake_r = self.calc_wake_radius(algo, mdata, fdata, tdata, downwind_index, x, ct)
210
210
 
211
211
  wdeltas = {}
212
- st_sel = (ct > 0) & (x > 0) & np.any(r < wake_r[:, :, None], axis=2)
212
+ st_sel = (x > 1e-8) & (ct > 1e-8) & np.any(r < wake_r[:, :, None], axis=2)
213
213
  if np.any(st_sel):
214
214
  x = x[st_sel]
215
215
  r = r[st_sel]
@@ -140,9 +140,9 @@ class Bastankhah2014(GaussianWakeModel):
140
140
  downwind_index=downwind_index,
141
141
  upcast=True,
142
142
  )
143
-
143
+
144
144
  # select targets:
145
- st_sel = (x > 0) & (ct > 0)
145
+ st_sel = (x > 1e-8) & (ct > 1e-8)
146
146
  if np.any(st_sel):
147
147
  # apply selection:
148
148
  x = x[st_sel]
@@ -146,13 +146,13 @@ class Bastankhah2016Model(Model):
146
146
  The k parameter values, shape: (n_states, n_targets)
147
147
 
148
148
  """
149
-
150
149
  # store parameters:
151
150
  out = {self.PARS: self.pars}
152
151
  out[self.CHECK] = (
153
- mdata[FC.STATE][0],
152
+ mdata.states_i0(counter=True),
153
+ mdata.n_states,
154
154
  downwind_index,
155
- x.shape,
155
+ hash(x.tobytes()),
156
156
  )
157
157
 
158
158
  # get D:
@@ -180,7 +180,7 @@ class Bastankhah2016Model(Model):
180
180
  )
181
181
 
182
182
  # select targets:
183
- st_sel = (x > 0) & (ct > 0.0)
183
+ st_sel = (x > 1e-8) & (ct > 1e-8)
184
184
  if np.any(st_sel):
185
185
  # get ws:
186
186
  ws = super().get_data(
@@ -329,7 +329,7 @@ class Bastankhah2016Model(Model):
329
329
 
330
330
  # update mdata:
331
331
  out[self.ST_SEL] = st_sel
332
- mdata[self.MDATA_KEY] = out
332
+ mdata.add(self.MDATA_KEY, out, None)
333
333
 
334
334
  def has_data(self, mdata, downwind_index, x):
335
335
  """
@@ -352,9 +352,10 @@ class Bastankhah2016Model(Model):
352
352
 
353
353
  """
354
354
  check = (
355
- mdata[FC.STATE][0],
355
+ mdata.states_i0(counter=True),
356
+ mdata.n_states,
356
357
  downwind_index,
357
- x.shape,
358
+ hash(x.tobytes()),
358
359
  )
359
360
  return self.MDATA_KEY in mdata and mdata[self.MDATA_KEY][self.CHECK] == check
360
361
 
@@ -88,7 +88,7 @@ class JensenWake(TopHatWakeModel):
88
88
  fdata=fdata,
89
89
  tdata=tdata,
90
90
  downwind_index=downwind_index,
91
- upcast=False,
91
+ upcast=True,
92
92
  )
93
93
 
94
94
  k = self.wake_k(
@@ -160,7 +160,7 @@ class TurbOParkWake(GaussianWakeModel):
160
160
  )
161
161
 
162
162
  # select targets:
163
- st_sel = (x > 1e-5) & (ct > 0.0)
163
+ st_sel = (x > 1e-8) & (ct > 1e-8)
164
164
  if np.any(st_sel):
165
165
  # apply selection:
166
166
  x = x[st_sel]
@@ -443,7 +443,7 @@ class TurbOParkWakeIX(GaussianWakeModel):
443
443
  )
444
444
 
445
445
  # select targets:
446
- st_sel = (x > 1e-5) & (ct > 0.0)
446
+ st_sel = (x > 1e-8) & (ct > 1e-8)
447
447
  if np.any(st_sel):
448
448
  # apply selection:
449
449
  # x = x[st_sel]
foxes/output/__init__.py CHANGED
@@ -16,5 +16,8 @@ from .slice_data import SliceData
16
16
  from .rotor_point_plots import RotorPointPlot
17
17
  from .state_turbine_table import StateTurbineTable
18
18
 
19
- from .flow_plots_2d import FlowPlots2D, SeqFlowAnimationPlugin
19
+ from .flow_plots_2d import FlowPlots2D
20
+ from .seq_plugins import SeqFlowAnimationPlugin, SeqWakeDebugPlugin
21
+
20
22
  from . import grids
23
+ from . import seq_plugins
@@ -288,8 +288,6 @@ class FarmLayoutOutput(Output):
288
288
  """
289
289
  Writes the layout plot to file.
290
290
 
291
- The kwargs are forwarded to self.get_figure
292
-
293
291
  Parameters
294
292
  ----------
295
293
  file_path: str
@@ -297,6 +295,8 @@ class FarmLayoutOutput(Output):
297
295
  for default
298
296
  fontsize: int
299
297
  Size of the turbine numbers
298
+ kwargs: dict, optional
299
+ Additional arguments for get_figure()
300
300
 
301
301
  """
302
302
 
@@ -1,3 +1,2 @@
1
1
  from .flow_plots import FlowPlots2D
2
- from .seq_flow_ani_plugin import SeqFlowAnimationPlugin
3
2
  from .get_fig import get_fig
@@ -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: