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
foxes/__init__.py CHANGED
@@ -3,24 +3,28 @@ Farm Optimization and eXtended yield Evaluation Software
3
3
 
4
4
  """
5
5
 
6
- from .config import config, get_path # noqa: F401
7
- from .core import Engine, WindFarm, Turbine, get_engine, reset_engine # noqa: F401
8
- from .models import ModelBook # noqa: F401
9
- from .data import (
10
- parse_Pct_file_name,
11
- parse_Pct_two_files,
12
- FARM,
13
- STATES,
14
- PCTCURVE,
15
- StaticData,
16
- ) # noqa: F401
6
+ from .config import config as config
7
+ from .config import get_path as get_path
8
+ from .core import Engine as Engine
9
+ from .core import WindFarm as WindFarm
10
+ from .core import Turbine as Turbine
11
+ from .core import get_engine as get_engine
12
+ from .core import reset_engine as reset_engine
13
+ from .models import ModelBook as ModelBook
17
14
 
18
- from . import algorithms # noqa: F401
19
- from . import engines # noqa: F401
20
- from . import models # noqa: F401
21
- from . import input # noqa: F401
22
- from . import output # noqa: F401
23
- from . import utils # noqa: F401
15
+ from .data import parse_Pct_file_name as parse_Pct_file_name
16
+ from .data import parse_Pct_two_files as parse_Pct_two_files
17
+ from .data import FARM as FARM
18
+ from .data import STATES as STATES
19
+ from .data import PCTCURVE as PCTCURVE
20
+ from .data import StaticData as StaticData
21
+
22
+ from . import algorithms as algorithms
23
+ from . import engines as engines
24
+ from . import models as models
25
+ from . import input as input
26
+ from . import output as output
27
+ from . import utils as utils
24
28
 
25
29
  import importlib
26
30
  from pathlib import Path
@@ -2,10 +2,10 @@
2
2
  Algorithms define the main calculation routines.
3
3
  """
4
4
 
5
- from .downwind.downwind import Downwind
6
- from .iterative.iterative import Iterative
7
- from .sequential import Sequential
5
+ from .downwind.downwind import Downwind as Downwind
6
+ from .iterative.iterative import Iterative as Iterative
7
+ from .sequential import Sequential as Sequential
8
8
 
9
- from . import downwind
10
- from . import iterative
11
- from . import sequential
9
+ from . import downwind as downwind
10
+ from . import iterative as iterative
11
+ from . import sequential as sequential
@@ -1,3 +1,3 @@
1
- from .downwind import Downwind
1
+ from .downwind import Downwind as Downwind
2
2
 
3
- from . import models
3
+ from . import models as models
@@ -32,6 +32,8 @@ class Downwind(Algorithm):
32
32
  partial_wakes: dict
33
33
  The partial wakes mapping. Key: wake model name,
34
34
  value: foxes.core.PartialWakesModel
35
+ deflection: foxes.core.WakeDeflection
36
+ The wake deflection model
35
37
  ground_models: dict
36
38
  The ground models mapping. Key: wake model name,
37
39
  value: foxes.core.GroundModel
@@ -70,6 +72,7 @@ class Downwind(Algorithm):
70
72
  wake_models,
71
73
  rotor_model="centre",
72
74
  wake_frame="rotor_wd",
75
+ wake_deflection="no_deflection",
73
76
  partial_wakes=None,
74
77
  ground_models=None,
75
78
  farm_controller="basic_ctrl",
@@ -94,6 +97,8 @@ class Downwind(Algorithm):
94
97
  wake_frame: str
95
98
  The wake frame. Will be looked up in the
96
99
  model book
100
+ deflection: foxes.core.WakeDeflection, optional
101
+ The wake deflection model
97
102
  partial_wakes: dict, list or str, optional
98
103
  The partial wakes mapping. Key: wake model name,
99
104
  value: partial wake model name
@@ -123,6 +128,9 @@ class Downwind(Algorithm):
123
128
  self.__wake_frame = self.mbook.wake_frames.get_item(wake_frame)
124
129
  self.wake_frame.name = wake_frame
125
130
 
131
+ self.__wake_deflection = self.mbook.wake_deflections.get_item(wake_deflection)
132
+ self.wake_deflection.name = wake_deflection
133
+
126
134
  self.__wake_models = {}
127
135
  for w in wake_models:
128
136
  m = self.mbook.wake_models.get_item(w)
@@ -251,6 +259,19 @@ class Downwind(Algorithm):
251
259
  """
252
260
  return self.__wake_frame
253
261
 
262
+ @property
263
+ def wake_deflection(self):
264
+ """
265
+ The wake deflection
266
+
267
+ Returns
268
+ -------
269
+ m: foxes.core.WakeDeflection
270
+ The wake deflection model
271
+
272
+ """
273
+ return self.__wake_deflection
274
+
254
275
  @property
255
276
  def partial_wakes(self):
256
277
  """
@@ -310,6 +331,15 @@ class Downwind(Algorithm):
310
331
  """
311
332
  return getattr(mdls, name)
312
333
 
334
+ def update_n_turbines(self):
335
+ """
336
+ Reset the number of turbines,
337
+ according to self.farm
338
+ """
339
+ if self.n_turbines != self.farm.n_turbines:
340
+ super().update_n_turbines()
341
+ self.farm_controller.find_turbine_types(self)
342
+
313
343
  def print_deco(self, func_name=None, n_points=None):
314
344
  """
315
345
  Helper function for printing model names
@@ -334,25 +364,26 @@ class Downwind(Algorithm):
334
364
  if n_points is not None:
335
365
  print(f" n_points : {n_points}")
336
366
  print(deco)
337
- print(f" states : {self.states}")
338
- print(f" rotor : {self.rotor_model}")
367
+ print(f" states : {self.states}")
368
+ print(f" rotor : {self.rotor_model}")
339
369
  print(f" controller: {self.farm_controller}")
340
370
  print(f" wake frame: {self.wake_frame}")
371
+ print(f" deflection: {self.wake_deflection}")
341
372
  print(deco)
342
- print(f" wakes:")
373
+ print(" wakes:")
343
374
  for i, w in enumerate(self.wake_models.values()):
344
375
  print(f" {i}) {w.name}: {w}")
345
376
  print(deco)
346
- print(f" partial wakes:")
377
+ print(" partial wakes:")
347
378
  for i, (w, p) in enumerate(self.partial_wakes.items()):
348
379
  print(f" {i}) {w}: {p.name}, {p}")
349
380
  print(deco)
350
- print(f" turbine models:")
381
+ print(" turbine models:")
351
382
  for i, m in enumerate(self.farm_controller.pre_rotor_models.models):
352
383
  print(f" {i}) {m.name}: {m} [pre-rotor]")
353
384
  for i, m in enumerate(self.farm_controller.post_rotor_models.models):
354
385
  print(
355
- f" {i+len(self.farm_controller.pre_rotor_models.models)}) {m.name}: {m}"
386
+ f" {i + len(self.farm_controller.pre_rotor_models.models)}) {m.name}: {m}"
356
387
  )
357
388
  print(deco)
358
389
  print()
@@ -364,7 +395,7 @@ class Downwind(Algorithm):
364
395
  if self.verbosity > 0:
365
396
  deco = "-" * 50
366
397
  print(f"\n{deco}")
367
- print(f" Model oder")
398
+ print(" Model oder")
368
399
  print(f"{deco}")
369
400
 
370
401
  for i, m in enumerate(mlist.models):
@@ -402,6 +433,7 @@ class Downwind(Algorithm):
402
433
  self.states,
403
434
  self.farm_controller,
404
435
  self.rotor_model,
436
+ self.wake_deflection,
405
437
  self.wake_frame,
406
438
  ]
407
439
  mdls += list(self.wake_models.values())
@@ -463,7 +495,7 @@ class Downwind(Algorithm):
463
495
  calc_pars.append(calc_parameters.get(mlist.models[-1].name, {}))
464
496
 
465
497
  # 6) reorder back to state-turbine dimensions:
466
- if outputs != False:
498
+ if not isinstance(outputs, bool) or outputs:
467
499
  mlist.models.append(self.get_model("ReorderFarmOutput")(outputs))
468
500
  calc_pars.append(calc_parameters.get(mlist.models[-1].name, {}))
469
501
 
@@ -573,8 +605,8 @@ class Downwind(Algorithm):
573
605
  # get input model data:
574
606
  model_data = self.get_models_data()
575
607
  self.print("\nInput data:\n\n", model_data, "\n")
576
- self.print(f"\nFarm variables:", ", ".join(self.farm_vars))
577
- self.print(f"\nOutput variables:", ", ".join(outputs))
608
+ self.print("\nFarm variables:", ", ".join(self.farm_vars))
609
+ self.print("\nOutput variables:", ", ".join(outputs))
578
610
 
579
611
  # run main calculation:
580
612
  farm_results = super().calc_farm(
@@ -779,7 +811,7 @@ class Downwind(Algorithm):
779
811
  if persist_mdata:
780
812
  model_data = model_data.persist()
781
813
  self.print("\nInput data:\n\n", model_data, "\n")
782
- self.print(f"\nOutput farm variables:", ", ".join(self.farm_vars))
814
+ self.print("\nOutput farm variables:", ", ".join(self.farm_vars))
783
815
 
784
816
  # chunk farm results:
785
817
  self.print("\nInput farm data:\n\n", farm_results, "\n")
@@ -798,7 +830,7 @@ class Downwind(Algorithm):
798
830
 
799
831
  # check vars:
800
832
  ovars = mlist.output_point_vars(self) if outputs is None else outputs
801
- self.print(f"\nOutput point variables:", ", ".join(ovars))
833
+ self.print("\nOutput point variables:", ", ".join(ovars))
802
834
 
803
835
  # calculate:
804
836
  point_results = super().calc_points(
@@ -1,6 +1,6 @@
1
- from .set_amb_farm_results import SetAmbFarmResults
2
- from .set_amb_point_results import SetAmbPointResults
3
- from .farm_wakes_calc import FarmWakesCalculation
4
- from .point_wakes_calc import PointWakesCalculation
5
- from .init_farm_data import InitFarmData
6
- from .reorder_farm_output import ReorderFarmOutput
1
+ from .set_amb_farm_results import SetAmbFarmResults as SetAmbFarmResults
2
+ from .set_amb_point_results import SetAmbPointResults as SetAmbPointResults
3
+ from .farm_wakes_calc import FarmWakesCalculation as FarmWakesCalculation
4
+ from .point_wakes_calc import PointWakesCalculation as PointWakesCalculation
5
+ from .init_farm_data import InitFarmData as InitFarmData
6
+ from .reorder_farm_output import ReorderFarmOutput as ReorderFarmOutput
@@ -1,7 +1,7 @@
1
1
  import numpy as np
2
2
  from copy import deepcopy
3
3
 
4
- from foxes.core import FarmDataModel, TData
4
+ from foxes.core import FarmDataModel
5
5
  import foxes.constants as FC
6
6
  import foxes.variables as FV
7
7
 
@@ -69,8 +69,14 @@ class FarmWakesCalculation(FarmDataModel):
69
69
  for wname, wmodel in algo.wake_models.items():
70
70
  pwake = algo.partial_wakes[wname]
71
71
  if pwake.name not in pwake2tdata:
72
- tpoints, tweights = pwake.get_wake_points(algo, mdata, fdata)
73
- pwake2tdata[pwake.name] = TData.from_tpoints(tpoints, tweights)
72
+ wmodels = [
73
+ wm
74
+ for wn, wm in algo.wake_models.items()
75
+ if algo.partial_wakes[wn] is pwake
76
+ ]
77
+ pwake2tdata[pwake.name] = pwake.get_initial_tdata(
78
+ algo, mdata, fdata, amb_res, rwghts, wmodels
79
+ )
74
80
 
75
81
  def _get_wdata(tdatap, wdeltas, variables, s):
76
82
  """Helper function for wake data extraction"""
@@ -78,12 +84,10 @@ class FarmWakesCalculation(FarmDataModel):
78
84
  wdelta = {v: d[s] for v, d in wdeltas.items()}
79
85
  return tdata, wdelta
80
86
 
81
- def _evaluate(
82
- gmodel, tdata, amb_res, rwghts, wake_res, wdeltas, oi, wmodel, pwake
83
- ):
87
+ def _evaluate(gmodel, tdata, rwghts, wake_res, wdeltas, oi, wmodel, pwake):
84
88
  """Helper function for data evaluation at turbines"""
85
89
  wres = gmodel.finalize_farm_wakes(
86
- algo, mdata, fdata, tdata, amb_res, rwghts, wdeltas, wmodel, oi, pwake
90
+ algo, mdata, fdata, tdata, rwghts, wdeltas, wmodel, oi, pwake
87
91
  )
88
92
 
89
93
  hres = {
@@ -124,7 +128,6 @@ class FarmWakesCalculation(FarmDataModel):
124
128
  _evaluate(
125
129
  gmodel,
126
130
  tdatap,
127
- amb_res,
128
131
  rwghts,
129
132
  wake_res,
130
133
  wdeltas,
@@ -149,7 +152,6 @@ class FarmWakesCalculation(FarmDataModel):
149
152
  _evaluate(
150
153
  gmodel,
151
154
  tdatap,
152
- amb_res,
153
155
  rwghts,
154
156
  wake_res,
155
157
  wdeltas,
@@ -86,7 +86,6 @@ class InitFarmData(FarmDataModel):
86
86
  # set X, Y, H, D:
87
87
  fdata[FV.D] = np.zeros((n_states, n_turbines), dtype=config.dtype_double)
88
88
  for ti, t in enumerate(algo.farm.turbines):
89
-
90
89
  if len(t.xy.shape) == 1:
91
90
  fdata[FV.TXYH][:, ti, :2] = t.xy[None, :]
92
91
  else:
@@ -1,4 +1,5 @@
1
1
  from foxes.core import PointDataModel
2
+ import foxes.variables as FV
2
3
 
3
4
 
4
5
  class PointWakesCalculation(PointDataModel):
@@ -114,17 +115,17 @@ class PointWakesCalculation(PointDataModel):
114
115
  (n_states, n_targets, n_tpoints)
115
116
 
116
117
  """
117
- res = {}
118
+
118
119
  wmodels = (
119
120
  algo.wake_models.values() if self.wake_models is None else self.wake_models
120
121
  )
122
+ pvrs = self.pvars + [FV.UV]
121
123
  for wmodel in wmodels:
122
124
  gmodel = algo.ground_models[wmodel.name]
123
125
 
124
126
  wdeltas = gmodel.new_point_wake_deltas(algo, mdata, fdata, tdata, wmodel)
125
127
 
126
- if len(set(self.pvars).intersection(wdeltas.keys())):
127
-
128
+ if len(set(pvrs).intersection(wdeltas.keys())):
128
129
  if downwind_index is None:
129
130
  for oi in range(fdata.n_turbines):
130
131
  gmodel.contribute_to_point_wakes(
@@ -135,18 +136,11 @@ class PointWakesCalculation(PointDataModel):
135
136
  algo, mdata, fdata, tdata, downwind_index, wdeltas, wmodel
136
137
  )
137
138
 
138
- for v in self.pvars:
139
- if v not in res and v in tdata:
140
- res[v] = tdata[v].copy()
139
+ gmodel.finalize_point_wakes(algo, mdata, fdata, tdata, wdeltas, wmodel)
141
140
 
142
- gmodel.finalize_point_wakes(algo, mdata, fdata, res, wdeltas, wmodel)
143
-
144
- for v in res.keys():
141
+ for v in tdata.keys():
145
142
  if v in wdeltas:
146
- res[v] += wdeltas[v]
147
-
148
- for v in res.keys():
149
- tdata[v] = res[v]
143
+ tdata[v] += wdeltas[v]
150
144
 
151
145
  if self.emodels is not None:
152
146
  self.emodels.calculate(algo, mdata, fdata, tdata, self.emodels_cpars)
@@ -60,7 +60,7 @@ class SetAmbPointResults(PointDataModel):
60
60
  """
61
61
  return [FV.var2amb[v] for v in self.vars] + [FV.WEIGHT]
62
62
 
63
- def calculate(self, algo, mdata, fdata, pdata):
63
+ def calculate(self, algo, mdata, fdata, tdata):
64
64
  """
65
65
  The main model calculation.
66
66
 
@@ -71,11 +71,11 @@ class SetAmbPointResults(PointDataModel):
71
71
  ----------
72
72
  algo: foxes.core.Algorithm
73
73
  The calculation algorithm
74
- mdata: foxes.core.Data
74
+ mdata: foxes.core.MData
75
75
  The model data
76
- fdata: foxes.core.Data
76
+ fdata: foxes.core.FData
77
77
  The farm data
78
- pdata: foxes.core.Data
78
+ tdata: foxes.core.TData
79
79
  The point data
80
80
 
81
81
  Returns
@@ -86,5 +86,5 @@ class SetAmbPointResults(PointDataModel):
86
86
 
87
87
  """
88
88
  for v in self.vars:
89
- pdata[FV.var2amb[v]] = pdata[v].copy()
90
- return {v: pdata[v] for v in self.output_point_vars(algo)}
89
+ tdata.add(FV.var2amb[v], tdata[v].copy(), tdata.dims[v])
90
+ return {v: tdata[v] for v in self.output_point_vars(algo)}
@@ -1,4 +1,8 @@
1
- from .iterative import Iterative
2
- from .models.convergence import ConvCrit, ConvCritList, ConvVarDelta, DefaultConv
1
+ from .iterative import Iterative as Iterative
3
2
 
4
- from . import models
3
+ from .models.convergence import ConvCrit as ConvCrit
4
+ from .models.convergence import ConvCritList as ConvCritList
5
+ from .models.convergence import ConvVarDelta as ConvVarDelta
6
+ from .models.convergence import DefaultConv as DefaultConv
7
+
8
+ from . import models as models
@@ -114,7 +114,7 @@ class Iterative(Downwind):
114
114
 
115
115
  """
116
116
  if self.initialized:
117
- raise ValueError(f"Attempt to set_urelax after initialization")
117
+ raise ValueError("Attempt to set_urelax after initialization")
118
118
  if self._urelax is None:
119
119
  self._urelax = Dict(
120
120
  first={},
@@ -219,7 +219,6 @@ class Iterative(Downwind):
219
219
 
220
220
  # do not rotate back from downwind order:
221
221
  if not self._final_run:
222
-
223
222
  # add under-relaxation during wake calculation:
224
223
  urelax = None
225
224
  if self._urelax is not None and len(self._urelax["pre_wake"]):
@@ -1,3 +1,7 @@
1
- from .convergence import ConvCrit, ConvCritList, ConvVarDelta, DefaultConv
2
- from .farm_wakes_calc import FarmWakesCalculation
3
- from .urelax import URelax
1
+ from .convergence import ConvCrit as ConvCrit
2
+ from .convergence import ConvCritList as ConvCritList
3
+ from .convergence import ConvVarDelta as ConvVarDelta
4
+ from .convergence import DefaultConv as DefaultConv
5
+
6
+ from .farm_wakes_calc import FarmWakesCalculation as FarmWakesCalculation
7
+ from .urelax import URelax as URelax
@@ -1,7 +1,7 @@
1
1
  import numpy as np
2
2
  from copy import deepcopy
3
3
 
4
- from foxes.core import FarmDataModel, TData
4
+ from foxes.core import FarmDataModel
5
5
  import foxes.constants as FC
6
6
  import foxes.variables as FV
7
7
 
@@ -99,8 +99,14 @@ class FarmWakesCalculation(FarmDataModel):
99
99
  for wname, wmodel in algo.wake_models.items():
100
100
  pwake = algo.partial_wakes[wname]
101
101
  if pwake.name not in pwake2tdata:
102
- tpoints, tweights = pwake.get_wake_points(algo, mdata, fdata)
103
- pwake2tdata[pwake.name] = TData.from_tpoints(tpoints, tweights)
102
+ wmodels = [
103
+ wm
104
+ for wn, wm in algo.wake_models.items()
105
+ if algo.partial_wakes[wn] is pwake
106
+ ]
107
+ pwake2tdata[pwake.name] = pwake.get_initial_tdata(
108
+ algo, mdata, fdata, amb_res, rwghts, wmodels
109
+ )
104
110
 
105
111
  def _get_wdata(tdatap, wdeltas, variables, s):
106
112
  """Helper function for wake data extraction"""
@@ -117,7 +123,6 @@ class FarmWakesCalculation(FarmDataModel):
117
123
  wdeltas = pwake.new_wake_deltas(algo, mdata, fdata, tdatap, wmodel)
118
124
 
119
125
  for oi in range(n_turbines):
120
-
121
126
  if oi > 0:
122
127
  tdata, wdelta = _get_wdata(
123
128
  tdatap, wdeltas, [FC.STATE, FC.TARGET], np.s_[:, :oi]
@@ -140,7 +145,6 @@ class FarmWakesCalculation(FarmDataModel):
140
145
  mdata,
141
146
  fdata,
142
147
  tdatap,
143
- amb_res,
144
148
  rwghts,
145
149
  wdeltas,
146
150
  wmodel,
@@ -1,4 +1,4 @@
1
- from .sequential import Sequential
2
- from .models import SequentialPlugin
1
+ from .sequential import Sequential as Sequential
2
+ from .models import SequentialPlugin as SequentialPlugin
3
3
 
4
- from . import models
4
+ from . import models as models
@@ -1,2 +1,2 @@
1
- from .plugin import SequentialPlugin
2
- from .seq_state import SeqState
1
+ from .plugin import SequentialPlugin as SequentialPlugin
2
+ from .seq_state import SeqState as SeqState
@@ -154,7 +154,7 @@ class Sequential(Iterative):
154
154
  if self._verbo0 > 0:
155
155
  print("\nInput data:\n")
156
156
  print(self._model_data)
157
- print(f"\nOutput farm variables:", ", ".join(self.farm_vars))
157
+ print("\nOutput farm variables:", ", ".join(self.farm_vars))
158
158
  print()
159
159
 
160
160
  sts = self._model_data[FC.STATE].to_numpy()
@@ -188,7 +188,6 @@ class Sequential(Iterative):
188
188
  """Run calculation for current step, then iterate to next"""
189
189
 
190
190
  if self._i < len(self._inds):
191
-
192
191
  self._counter = self._i
193
192
  self.states._counter = self._i
194
193
  self.states._size = 1
@@ -401,7 +400,7 @@ class Sequential(Iterative):
401
400
 
402
401
  """
403
402
  if not self.iterating:
404
- raise ValueError(f"calc_farm call is only allowed during iterations")
403
+ raise ValueError("calc_farm call is only allowed during iterations")
405
404
  return self.cur_farm_results
406
405
 
407
406
  def calc_points(
@@ -433,6 +432,6 @@ class Sequential(Iterative):
433
432
 
434
433
  """
435
434
  if not self.iterating:
436
- raise ValueError(f"calc_points call is only allowed during iterations")
435
+ raise ValueError("calc_points call is only allowed during iterations")
437
436
 
438
437
  return super().calc_points(farm_results, points, finalize=False, **kwargs)
foxes/config/__init__.py CHANGED
@@ -1 +1,5 @@
1
- from .config import Config, config, get_path, get_input_path, get_output_path
1
+ from .config import Config as Config
2
+ from .config import config as config
3
+ from .config import get_path as get_path
4
+ from .config import get_input_path as get_input_path
5
+ from .config import get_output_path as get_output_path
foxes/constants.py CHANGED
@@ -1,3 +1,8 @@
1
+ XY = "xy"
2
+ """ The vector (x, y)
3
+ :group: foxes.variables
4
+ """
5
+
1
6
  XYH = "xyh"
2
7
  """ The vector (x, y, height)
3
8
  :group: foxes.variables
@@ -146,6 +151,17 @@ BLOCK_CONVERGENCE = "block_convergence"
146
151
  """
147
152
 
148
153
 
154
+ WDEFL_ROT_ANGLE = "wake_deflection_rotation_angle"
155
+ """Identifier for the wake deflection rotation angle data
156
+ :group: foxes.constants
157
+ """
158
+
159
+ WDEFL_DWS_FACTOR = "wake_deflection_deltaws_factor"
160
+ """Identifier for the wake deflection delta wind speed factor data
161
+ :group: foxes.constants
162
+ """
163
+
164
+
149
165
  KAPPA = 0.41
150
166
  """ The Von Karman constant
151
167
  :group: foxes.constants
foxes/core/__init__.py CHANGED
@@ -2,25 +2,48 @@
2
2
  Abstract classes and core functionality.
3
3
  """
4
4
 
5
- from .data import Data, MData, FData, TData
6
- from .model import Model
7
- from .data_calc_model import DataCalcModel
8
- from .engine import Engine, get_engine, has_engine, reset_engine
9
- from .states import States, ExtendedStates
10
- from .wind_farm import WindFarm
11
- from .algorithm import Algorithm
12
- from .farm_data_model import FarmDataModel, FarmDataModelList
13
- from .point_data_model import PointDataModel, PointDataModelList
14
- from .rotor_model import RotorModel
15
- from .farm_model import FarmModel
16
- from .turbine_model import TurbineModel
17
- from .turbine_type import TurbineType
18
- from .farm_controller import FarmController
19
- from .turbine import Turbine
20
- from .partial_wakes_model import PartialWakesModel
21
- from .wake_frame import WakeFrame
22
- from .wake_model import WakeModel, TurbineInductionModel, WakeK
23
- from .wake_superposition import WakeSuperposition
24
- from .vertical_profile import VerticalProfile
25
- from .axial_induction_model import AxialInductionModel
26
- from .ground_model import GroundModel
5
+ from .model import Model as Model
6
+ from .data_calc_model import DataCalcModel as DataCalcModel
7
+ from .wind_farm import WindFarm as WindFarm
8
+ from .algorithm import Algorithm as Algorithm
9
+ from .rotor_model import RotorModel as RotorModel
10
+ from .farm_model import FarmModel as FarmModel
11
+ from .turbine_model import TurbineModel as TurbineModel
12
+ from .turbine_type import TurbineType as TurbineType
13
+ from .farm_controller import FarmController as FarmController
14
+ from .turbine import Turbine as Turbine
15
+ from .partial_wakes_model import PartialWakesModel as PartialWakesModel
16
+ from .wake_frame import WakeFrame as WakeFrame
17
+ from .wake_deflection import WakeDeflection as WakeDeflection
18
+ from .vertical_profile import VerticalProfile as VerticalProfile
19
+ from .axial_induction_model import AxialInductionModel as AxialInductionModel
20
+ from .ground_model import GroundModel as GroundModel
21
+
22
+ from .data import Data as Data
23
+ from .data import MData as MData
24
+ from .data import FData as FData
25
+ from .data import TData as TData
26
+
27
+ from .engine import Engine as Engine
28
+ from .engine import get_engine as get_engine
29
+ from .engine import has_engine as has_engine
30
+ from .engine import reset_engine as reset_engine
31
+
32
+ from .states import States as States
33
+ from .states import ExtendedStates as ExtendedStates
34
+
35
+ from .farm_data_model import FarmDataModel as FarmDataModel
36
+ from .farm_data_model import FarmDataModelList as FarmDataModelList
37
+
38
+ from .point_data_model import PointDataModel as PointDataModel
39
+ from .point_data_model import PointDataModelList as PointDataModelList
40
+
41
+ from .wake_model import WakeModel as WakeModel
42
+ from .wake_model import SingleTurbineWakeModel as SingleTurbineWakeModel
43
+ from .wake_model import TurbineInductionModel as TurbineInductionModel
44
+ from .wake_model import WakeK as WakeK
45
+
46
+ from .wake_superposition import WakeSuperposition as WakeSuperposition
47
+ from .wake_superposition import (
48
+ WindVectorWakeSuperposition as WindVectorWakeSuperposition,
49
+ )
foxes/core/algorithm.py CHANGED
@@ -472,7 +472,6 @@ class Algorithm(Model):
472
472
  n_targets = int(tdata.n_targets if tdata is not None else 0)
473
473
 
474
474
  if prev_s > 0 or prev_t > 0:
475
-
476
475
  inds = np.array(
477
476
  [
478
477
  [