foxes 1.3__py3-none-any.whl → 1.5__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 (228) 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/field_data_nc/run.py +1 -1
  7. examples/induction/run.py +3 -3
  8. examples/multi_height/run.py +1 -1
  9. examples/power_mask/run.py +2 -2
  10. examples/quickstart/run.py +0 -1
  11. examples/random_timeseries/run.py +3 -4
  12. examples/scan_row/run.py +3 -3
  13. examples/sequential/run.py +33 -10
  14. examples/single_state/run.py +3 -4
  15. examples/states_lookup_table/run.py +3 -3
  16. examples/streamline_wakes/run.py +29 -6
  17. examples/tab_file/run.py +3 -3
  18. examples/timelines/run.py +29 -5
  19. examples/timeseries/run.py +3 -3
  20. examples/timeseries_slurm/run.py +3 -3
  21. examples/wind_rose/run.py +3 -3
  22. examples/yawed_wake/run.py +19 -9
  23. foxes/__init__.py +21 -17
  24. foxes/algorithms/__init__.py +6 -6
  25. foxes/algorithms/downwind/__init__.py +2 -2
  26. foxes/algorithms/downwind/downwind.py +49 -17
  27. foxes/algorithms/downwind/models/__init__.py +6 -6
  28. foxes/algorithms/downwind/models/farm_wakes_calc.py +11 -9
  29. foxes/algorithms/downwind/models/init_farm_data.py +58 -29
  30. foxes/algorithms/downwind/models/point_wakes_calc.py +7 -13
  31. foxes/algorithms/downwind/models/set_amb_farm_results.py +1 -1
  32. foxes/algorithms/downwind/models/set_amb_point_results.py +6 -6
  33. foxes/algorithms/iterative/__init__.py +7 -3
  34. foxes/algorithms/iterative/iterative.py +1 -2
  35. foxes/algorithms/iterative/models/__init__.py +7 -3
  36. foxes/algorithms/iterative/models/farm_wakes_calc.py +9 -5
  37. foxes/algorithms/sequential/__init__.py +3 -3
  38. foxes/algorithms/sequential/models/__init__.py +2 -2
  39. foxes/algorithms/sequential/sequential.py +3 -4
  40. foxes/config/__init__.py +5 -1
  41. foxes/constants.py +16 -0
  42. foxes/core/__init__.py +45 -22
  43. foxes/core/algorithm.py +5 -6
  44. foxes/core/data.py +94 -22
  45. foxes/core/data_calc_model.py +4 -2
  46. foxes/core/engine.py +42 -53
  47. foxes/core/farm_controller.py +2 -2
  48. foxes/core/farm_data_model.py +16 -13
  49. foxes/core/ground_model.py +4 -13
  50. foxes/core/model.py +24 -6
  51. foxes/core/partial_wakes_model.py +147 -10
  52. foxes/core/point_data_model.py +21 -17
  53. foxes/core/rotor_model.py +4 -3
  54. foxes/core/states.py +2 -3
  55. foxes/core/turbine.py +2 -1
  56. foxes/core/wake_deflection.py +130 -0
  57. foxes/core/wake_model.py +222 -9
  58. foxes/core/wake_superposition.py +122 -4
  59. foxes/core/wind_farm.py +6 -6
  60. foxes/data/__init__.py +7 -2
  61. foxes/data/states/point_cloud_100.nc +0 -0
  62. foxes/data/states/weibull_cloud_4.nc +0 -0
  63. foxes/data/states/weibull_grid.nc +0 -0
  64. foxes/data/states/weibull_sectors_12.csv +13 -0
  65. foxes/data/states/weibull_sectors_12.nc +0 -0
  66. foxes/engines/__init__.py +14 -15
  67. foxes/engines/dask.py +42 -20
  68. foxes/engines/default.py +2 -2
  69. foxes/engines/numpy.py +11 -13
  70. foxes/engines/pool.py +20 -11
  71. foxes/engines/single.py +8 -6
  72. foxes/input/__init__.py +3 -3
  73. foxes/input/farm_layout/__init__.py +9 -8
  74. foxes/input/farm_layout/from_arrays.py +68 -0
  75. foxes/input/farm_layout/from_csv.py +1 -1
  76. foxes/input/farm_layout/ring.py +0 -1
  77. foxes/input/states/__init__.py +28 -12
  78. foxes/input/states/create/__init__.py +3 -2
  79. foxes/input/states/dataset_states.py +710 -0
  80. foxes/input/states/field_data.py +531 -0
  81. foxes/input/states/multi_height.py +11 -6
  82. foxes/input/states/one_point_flow.py +1 -4
  83. foxes/input/states/point_cloud_data.py +618 -0
  84. foxes/input/states/scan.py +2 -0
  85. foxes/input/states/single.py +3 -1
  86. foxes/input/states/states_table.py +23 -30
  87. foxes/input/states/weibull_sectors.py +330 -0
  88. foxes/input/states/wrg_states.py +8 -6
  89. foxes/input/yaml/__init__.py +9 -3
  90. foxes/input/yaml/dict.py +42 -41
  91. foxes/input/yaml/windio/__init__.py +10 -5
  92. foxes/input/yaml/windio/read_attributes.py +42 -29
  93. foxes/input/yaml/windio/read_farm.py +17 -15
  94. foxes/input/yaml/windio/read_fields.py +4 -2
  95. foxes/input/yaml/windio/read_outputs.py +25 -15
  96. foxes/input/yaml/windio/read_site.py +172 -11
  97. foxes/input/yaml/windio/windio.py +23 -11
  98. foxes/input/yaml/yaml.py +1 -0
  99. foxes/models/__init__.py +15 -14
  100. foxes/models/axial_induction/__init__.py +2 -2
  101. foxes/models/farm_controllers/__init__.py +1 -1
  102. foxes/models/farm_models/__init__.py +1 -1
  103. foxes/models/ground_models/__init__.py +3 -2
  104. foxes/models/ground_models/wake_mirror.py +3 -3
  105. foxes/models/model_book.py +190 -63
  106. foxes/models/partial_wakes/__init__.py +6 -6
  107. foxes/models/partial_wakes/axiwake.py +30 -5
  108. foxes/models/partial_wakes/centre.py +47 -0
  109. foxes/models/partial_wakes/rotor_points.py +41 -11
  110. foxes/models/partial_wakes/segregated.py +2 -25
  111. foxes/models/partial_wakes/top_hat.py +27 -2
  112. foxes/models/point_models/__init__.py +4 -4
  113. foxes/models/rotor_models/__init__.py +4 -3
  114. foxes/models/rotor_models/centre.py +1 -1
  115. foxes/models/rotor_models/direct_infusion.py +241 -0
  116. foxes/models/turbine_models/__init__.py +11 -11
  117. foxes/models/turbine_models/calculator.py +16 -3
  118. foxes/models/turbine_models/kTI_model.py +1 -0
  119. foxes/models/turbine_models/lookup_table.py +2 -0
  120. foxes/models/turbine_models/power_mask.py +1 -0
  121. foxes/models/turbine_models/rotor_centre_calc.py +2 -0
  122. foxes/models/turbine_models/sector_management.py +1 -0
  123. foxes/models/turbine_models/set_farm_vars.py +3 -9
  124. foxes/models/turbine_models/table_factors.py +2 -0
  125. foxes/models/turbine_models/thrust2ct.py +1 -0
  126. foxes/models/turbine_models/yaw2yawm.py +2 -0
  127. foxes/models/turbine_models/yawm2yaw.py +2 -0
  128. foxes/models/turbine_types/PCt_file.py +2 -6
  129. foxes/models/turbine_types/PCt_from_two.py +1 -2
  130. foxes/models/turbine_types/__init__.py +10 -9
  131. foxes/models/turbine_types/calculator_type.py +123 -0
  132. foxes/models/turbine_types/null_type.py +1 -0
  133. foxes/models/turbine_types/wsrho2PCt_from_two.py +2 -0
  134. foxes/models/turbine_types/wsti2PCt_from_two.py +3 -1
  135. foxes/models/vertical_profiles/__init__.py +7 -7
  136. foxes/models/wake_deflections/__init__.py +3 -0
  137. foxes/models/{wake_frames/yawed_wakes.py → wake_deflections/bastankhah2016.py} +32 -111
  138. foxes/models/wake_deflections/jimenez.py +277 -0
  139. foxes/models/wake_deflections/no_deflection.py +94 -0
  140. foxes/models/wake_frames/__init__.py +6 -7
  141. foxes/models/wake_frames/dynamic_wakes.py +12 -3
  142. foxes/models/wake_frames/rotor_wd.py +3 -1
  143. foxes/models/wake_frames/seq_dynamic_wakes.py +41 -7
  144. foxes/models/wake_frames/streamlines.py +8 -6
  145. foxes/models/wake_frames/timelines.py +9 -3
  146. foxes/models/wake_models/__init__.py +7 -7
  147. foxes/models/wake_models/dist_sliced.py +50 -84
  148. foxes/models/wake_models/gaussian.py +20 -0
  149. foxes/models/wake_models/induction/__init__.py +5 -5
  150. foxes/models/wake_models/induction/rankine_half_body.py +30 -71
  151. foxes/models/wake_models/induction/rathmann.py +65 -64
  152. foxes/models/wake_models/induction/self_similar.py +65 -68
  153. foxes/models/wake_models/induction/self_similar2020.py +0 -3
  154. foxes/models/wake_models/induction/vortex_sheet.py +71 -75
  155. foxes/models/wake_models/ti/__init__.py +2 -2
  156. foxes/models/wake_models/ti/crespo_hernandez.py +5 -3
  157. foxes/models/wake_models/ti/iec_ti.py +6 -4
  158. foxes/models/wake_models/top_hat.py +58 -7
  159. foxes/models/wake_models/wind/__init__.py +6 -4
  160. foxes/models/wake_models/wind/bastankhah14.py +25 -7
  161. foxes/models/wake_models/wind/bastankhah16.py +35 -3
  162. foxes/models/wake_models/wind/jensen.py +15 -2
  163. foxes/models/wake_models/wind/turbopark.py +28 -2
  164. foxes/models/wake_superpositions/__init__.py +18 -9
  165. foxes/models/wake_superpositions/ti_linear.py +4 -4
  166. foxes/models/wake_superpositions/ti_max.py +4 -4
  167. foxes/models/wake_superpositions/ti_pow.py +4 -4
  168. foxes/models/wake_superpositions/ti_quadratic.py +4 -4
  169. foxes/models/wake_superpositions/wind_vector.py +257 -0
  170. foxes/models/wake_superpositions/ws_linear.py +9 -10
  171. foxes/models/wake_superpositions/ws_max.py +8 -8
  172. foxes/models/wake_superpositions/ws_pow.py +8 -8
  173. foxes/models/wake_superpositions/ws_product.py +4 -4
  174. foxes/models/wake_superpositions/ws_quadratic.py +8 -8
  175. foxes/output/__init__.py +21 -19
  176. foxes/output/farm_layout.py +4 -2
  177. foxes/output/farm_results_eval.py +19 -16
  178. foxes/output/flow_plots_2d/__init__.py +2 -2
  179. foxes/output/flow_plots_2d/flow_plots.py +18 -0
  180. foxes/output/flow_plots_2d/get_fig.py +5 -2
  181. foxes/output/output.py +6 -1
  182. foxes/output/results_writer.py +1 -1
  183. foxes/output/rose_plot.py +13 -3
  184. foxes/output/rotor_point_plots.py +3 -0
  185. foxes/output/seq_plugins/__init__.py +2 -2
  186. foxes/output/seq_plugins/seq_flow_ani_plugin.py +0 -3
  187. foxes/output/seq_plugins/seq_wake_debug_plugin.py +0 -1
  188. foxes/output/state_turbine_map.py +3 -0
  189. foxes/output/turbine_type_curves.py +10 -8
  190. foxes/utils/__init__.py +37 -19
  191. foxes/utils/abl/__init__.py +4 -4
  192. foxes/utils/cubic_roots.py +1 -1
  193. foxes/utils/data_book.py +4 -3
  194. foxes/utils/dict.py +49 -37
  195. foxes/utils/exec_python.py +5 -5
  196. foxes/utils/factory.py +3 -5
  197. foxes/utils/geom2d/__init__.py +7 -5
  198. foxes/utils/geopandas_utils.py +2 -2
  199. foxes/utils/pandas_utils.py +4 -3
  200. foxes/utils/tab_files.py +0 -1
  201. foxes/utils/weibull.py +28 -0
  202. foxes/utils/wrg_utils.py +3 -1
  203. foxes/utils/xarray_utils.py +9 -2
  204. foxes/variables.py +67 -9
  205. {foxes-1.3.dist-info → foxes-1.5.dist-info}/METADATA +34 -63
  206. foxes-1.5.dist-info/RECORD +328 -0
  207. {foxes-1.3.dist-info → foxes-1.5.dist-info}/WHEEL +1 -1
  208. tests/1_verification/flappy_0_6/PCt_files/flappy/run.py +2 -3
  209. tests/1_verification/flappy_0_6/PCt_files/test_PCt_files.py +1 -1
  210. tests/1_verification/flappy_0_6/abl_states/flappy/run.py +0 -1
  211. tests/1_verification/flappy_0_6/partial_top_hat/flappy/run.py +0 -1
  212. tests/1_verification/flappy_0_6/partial_top_hat/test_partial_top_hat.py +0 -2
  213. tests/1_verification/flappy_0_6/row_Jensen_linear_centre/test_row_Jensen_linear_centre.py +0 -1
  214. tests/1_verification/flappy_0_6/row_Jensen_linear_tophat/test_row_Jensen_linear_tophat.py +0 -1
  215. tests/1_verification/flappy_0_6/row_Jensen_linear_tophat_IECTI2005/test_row_Jensen_linear_tophat_IECTI_2005.py +0 -1
  216. tests/1_verification/flappy_0_6/row_Jensen_linear_tophat_IECTI2019/test_row_Jensen_linear_tophat_IECTI_2019.py +0 -1
  217. tests/1_verification/flappy_0_6/row_Jensen_quadratic_centre/test_row_Jensen_quadratic_centre.py +0 -1
  218. tests/1_verification/flappy_0_6_2/grid_rotors/flappy/run.py +0 -2
  219. tests/1_verification/flappy_0_6_2/row_Bastankhah_Crespo/test_row_Bastankhah_Crespo.py +0 -1
  220. tests/1_verification/flappy_0_6_2/row_Bastankhah_linear_centre/flappy/run.py +0 -1
  221. tests/1_verification/flappy_0_6_2/row_Bastankhah_linear_centre/test_row_Bastankhah_linear_centre.py +0 -1
  222. foxes/input/states/field_data_nc.py +0 -847
  223. foxes/output/round.py +0 -10
  224. foxes/utils/pandas_helpers.py +0 -178
  225. foxes-1.3.dist-info/RECORD +0 -313
  226. {foxes-1.3.dist-info → foxes-1.5.dist-info}/entry_points.txt +0 -0
  227. {foxes-1.3.dist-info → foxes-1.5.dist-info/licenses}/LICENSE +0 -0
  228. {foxes-1.3.dist-info → foxes-1.5.dist-info}/top_level.txt +0 -0
foxes/utils/dict.py CHANGED
@@ -6,16 +6,11 @@ class Dict(dict):
6
6
  """
7
7
  A slightly enhanced dictionary.
8
8
 
9
- Attributes
10
- ----------
11
- name: str
12
- The dictionary name
13
-
14
9
  :group: utils
15
10
 
16
11
  """
17
12
 
18
- def __init__(self, *args, name=None, **kwargs):
13
+ def __init__(self, *args, _name=None, **kwargs):
19
14
  """
20
15
  Constructor.
21
16
 
@@ -23,38 +18,28 @@ class Dict(dict):
23
18
  ----------
24
19
  *args: tuple, optional
25
20
  Arguments passed to `dict`
26
- name: str, optional
21
+ _name: str, optional
27
22
  The dictionary name
28
23
  **kwargs: dict, optional
29
24
  Arguments passed to `dict`
30
25
 
31
26
  """
32
- tmp = dict()
33
- for a in args:
34
- tmp.update(
35
- {
36
- k: (
37
- Dict(d, name=f"{name}.{k}")
38
- if isinstance(d, dict) and not isinstance(d, Dict)
39
- else d
40
- )
41
- for k, d in a.items()
42
- }
43
- )
44
-
45
- super().__init__(
46
- **tmp,
47
- **{
48
- k: (
49
- Dict(d, name=k)
50
- if isinstance(d, dict) and not isinstance(d, Dict)
51
- else d
52
- )
53
- for k, d in kwargs.items()
54
- },
55
- )
27
+ super().__init__()
28
+ self._name = _name if _name is not None else type(self).__name__
29
+ self.update(*args, **kwargs)
30
+
31
+ @property
32
+ def name(self):
33
+ """
34
+ The dictionary name
35
+
36
+ Returns
37
+ -------
38
+ name: str
39
+ The dictionary name
56
40
 
57
- self.name = name if name is not None else type(self).__name__
41
+ """
42
+ return self._name
58
43
 
59
44
  def get_item(self, key, *deflt, prnt=True):
60
45
  """
@@ -77,9 +62,9 @@ class Dict(dict):
77
62
  """
78
63
  try:
79
64
  if len(deflt):
80
- assert (
81
- len(deflt) == 1
82
- ), f"Expecting a single default entry, got {len(deflt)}"
65
+ assert len(deflt) == 1, (
66
+ f"Expecting a single default entry, got {len(deflt)}"
67
+ )
83
68
  data = self.get(key, deflt[0])
84
69
  else:
85
70
  data = self[key]
@@ -93,7 +78,7 @@ class Dict(dict):
93
78
  raise e
94
79
 
95
80
  if isinstance(data, dict) and not isinstance(data, Dict):
96
- data = Dict(data, name=f"{self.name}.{key}")
81
+ data = Dict(data, _name=f"{self.name}.{key}")
97
82
 
98
83
  return data
99
84
 
@@ -121,6 +106,25 @@ class Dict(dict):
121
106
  del self[key]
122
107
  return data
123
108
 
109
+ def __setitem__(self, key, value):
110
+ if isinstance(value, list):
111
+ out = []
112
+ for i, x in enumerate(value):
113
+ if isinstance(x, dict) and not isinstance(x, Dict):
114
+ nme = f"{self.name}.{key}"
115
+ if len(value) > 1:
116
+ nme += f".{i}"
117
+ out.append(Dict(x, _name=nme))
118
+ else:
119
+ out.append(x)
120
+ value = out
121
+ elif isinstance(value, dict) and not isinstance(value, Dict):
122
+ out = Dict(_name=f"{self.name}.{key}")
123
+ out.update(value)
124
+ value = out
125
+
126
+ super().__setitem__(key, value)
127
+
124
128
  def __getitem__(self, key):
125
129
  try:
126
130
  return super().__getitem__(key)
@@ -129,6 +133,14 @@ class Dict(dict):
129
133
  e = f"{self.name}: Cannot find key '{key}'. Known keys: {k}"
130
134
  raise KeyError(e)
131
135
 
136
+ def update(self, *args, **kwargs):
137
+ """
138
+ Update the dictionary with the key/value pairs from other, overwriting existing keys.
139
+ """
140
+ other = dict(*args, **kwargs)
141
+ for k, v in other.items():
142
+ self[k] = v
143
+
132
144
  @classmethod
133
145
  def from_yaml(self, yml_file, verbosity=1):
134
146
  """
@@ -158,7 +170,7 @@ class Dict(dict):
158
170
  data = safe_load(stream)
159
171
  if data is None:
160
172
  data = {}
161
- dct = Dict(data, name=fpath.stem)
173
+ dct = Dict(data, _name=fpath.stem)
162
174
  _print(dct, level=2)
163
175
 
164
176
  return dct
@@ -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
@@ -107,7 +107,7 @@ class Factory:
107
107
  f"Factory '{name_template}': Require indicator before variable '{v}' in template, e.g. '{v}<{v}>'"
108
108
  )
109
109
 
110
- self.options = Dict(name=f"{self._pre[0]}_options")
110
+ self.options = Dict(_name=f"{self._pre[0]}_options")
111
111
  for v, o in options.items():
112
112
  if v not in self.variables:
113
113
  raise KeyError(
@@ -121,7 +121,7 @@ class Factory:
121
121
  raise TypeError(
122
122
  f"Factory '{name_template}': Found option for variable '{v}' that is not a str, {k}"
123
123
  )
124
- self.options[v] = Dict(name=f"{self._pre[0]}_options_{v}", **o)
124
+ self.options[v] = Dict(_name=f"{self._pre[0]}_options_{v}", **o)
125
125
  elif hasattr(o, "__call__"):
126
126
  self.options[v] = o
127
127
  else:
@@ -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)))
foxes/utils/wrg_utils.py CHANGED
@@ -42,7 +42,9 @@ class ReaderWRG:
42
42
  int(self._res),
43
43
  )
44
44
 
45
- cols_sel = lambda name, secs: [f"{name}_{i}" for i in range(secs)]
45
+ def cols_sel(name, secs):
46
+ """little helper to create column names"""
47
+ return [f"{name}_{i}" for i in range(secs)]
46
48
 
47
49
  cols = [0] * (8 + 3 * self._n_sectors)
48
50
  cols[0] = "utmx"
@@ -1,3 +1,5 @@
1
+ import numpy as np
2
+ from xarray import Dataset
1
3
  from pathlib import Path
2
4
 
3
5
  from foxes.variables import get_default_digits
@@ -31,18 +33,23 @@ def write_nc(
31
33
  """
32
34
  fpath = Path(fpath)
33
35
  if round is not None:
36
+ crds = {}
34
37
  for v in ds.coords.keys():
35
38
  d = round.get(v, get_default_digits(v))
36
39
  if d is not None:
37
40
  if verbosity > 1:
38
41
  print(f"File {fpath.name}: Rounding {v} to {d} decimals")
39
- ds[v].data = ds[v].data.round(decimals=d)
42
+ crds[v] = np.round(ds[v].to_numpy(), d)
43
+ else:
44
+ crds[v] = ds[v].to_numpy()
45
+ dvrs = {}
40
46
  for v in ds.data_vars.keys():
41
47
  d = round.get(v, get_default_digits(v))
42
48
  if d is not None:
43
49
  if verbosity > 1:
44
50
  print(f"File {fpath.name}: Rounding {v} to {d} decimals")
45
- ds[v].data = ds[v].data.round(decimals=d)
51
+ dvrs[v] = (ds[v].dims, np.round(ds[v].to_numpy(), d))
52
+ ds = Dataset(coords=crds, data_vars=dvrs)
46
53
 
47
54
  enc = None
48
55
  if complevel is not None and complevel > 0:
foxes/variables.py CHANGED
@@ -54,6 +54,21 @@ WD = "WD"
54
54
  :group: foxes.variables
55
55
  """
56
56
 
57
+ UV = "UV"
58
+ """ The 2D wind vector in m/s
59
+ :group: foxes.variables
60
+ """
61
+
62
+ U = "U"
63
+ """ The first horizontal wind vector component in m/s
64
+ :group: foxes.variables
65
+ """
66
+
67
+ V = "V"
68
+ """ The second horizontal wind vector component in m/s
69
+ :group: foxes.variables
70
+ """
71
+
57
72
  TI = "TI"
58
73
  """ The turbulence intensity
59
74
  :group: foxes.variables
@@ -128,6 +143,17 @@ calculated from third moment
128
143
  """
129
144
 
130
145
 
146
+ WEIBULL_A = "Weibull_A"
147
+ """ The Weibull scale parameter,
148
+ :group: foxes.variables
149
+ """
150
+
151
+ WEIBULL_k = "Weibull_k"
152
+ """ The Weibull shape parameter,
153
+ :group: foxes.variables
154
+ """
155
+
156
+
131
157
  AMB_WS = "AMB_WS"
132
158
  """ The ambient wind speed in m/s
133
159
  :group: foxes.variables
@@ -138,6 +164,21 @@ AMB_WD = "AMB_WD"
138
164
  :group: foxes.variables
139
165
  """
140
166
 
167
+ AMB_UV = "AMB_UV"
168
+ """ The ambient 2D wind vector in m/s
169
+ :group: foxes.variables
170
+ """
171
+
172
+ AMB_U = "AMB_U"
173
+ """ The first horizontal ambient wind vector component in m/s
174
+ :group: foxes.variables
175
+ """
176
+
177
+ AMB_V = "AMB_V"
178
+ """ The second horizontal ambient wind vector component in m/s
179
+ :group: foxes.variables
180
+ """
181
+
141
182
  AMB_TI = "AMB_TI"
142
183
  """ The ambient turbulence intensity
143
184
  :group: foxes.variables
@@ -203,6 +244,16 @@ calculated from third moment
203
244
  :group: foxes.variables
204
245
  """
205
246
 
247
+ AMB_WEIBULL_A = "AMB_Weibull_A"
248
+ """ Ambient Weibull scale parameter,
249
+ :group: foxes.variables
250
+ """
251
+
252
+ AMB_WEIBULL_k = "AMB_Weibull_k"
253
+ """ Ambient Weibull shape parameter,
254
+ :group: foxes.variables
255
+ """
256
+
206
257
 
207
258
  var2amb = {
208
259
  v: f"AMB_{v}"
@@ -219,8 +270,13 @@ var2amb = {
219
270
  REWS,
220
271
  REWS2,
221
272
  REWS3,
273
+ WEIBULL_A,
274
+ WEIBULL_k,
222
275
  YLD,
223
276
  CAP,
277
+ UV,
278
+ U,
279
+ V,
224
280
  ]
225
281
  }
226
282
  """ Mapping from variable to the corresponding
@@ -282,9 +338,10 @@ PA_BETA = "PA_beta"
282
338
  :group: foxes.variables
283
339
  """
284
340
 
285
- DEFAULT_DIGITS = {
341
+ DEFAULT_DIGITS = 4
342
+
343
+ ROUND_DIGITS = {
286
344
  WD: 3,
287
- WS: 4,
288
345
  TI: 6,
289
346
  RHO: 5,
290
347
  P: 3,
@@ -293,10 +350,14 @@ DEFAULT_DIGITS = {
293
350
  YLD: 3,
294
351
  CAP: 5,
295
352
  EFF: 5,
353
+ WEIBULL_A: 3,
354
+ WEIBULL_k: 3,
355
+ YAW: 3,
356
+ YAWM: 3,
296
357
  }
297
- """ The default output digits
298
- :group: foxes.variables
299
- """
358
+ ROUND_DIGITS.update(
359
+ {var2amb[v]: ROUND_DIGITS[v] for v in var2amb.keys() if v in ROUND_DIGITS}
360
+ )
300
361
 
301
362
 
302
363
  def get_default_digits(variable):
@@ -314,7 +375,4 @@ def get_default_digits(variable):
314
375
  The default number of output digits
315
376
 
316
377
  """
317
- v = amb2var.get(variable, variable)
318
- if v in [REWS, REWS2, REWS3]:
319
- v = WS
320
- return DEFAULT_DIGITS.get(v, None)
378
+ return ROUND_DIGITS.get(variable, DEFAULT_DIGITS)
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.2
1
+ Metadata-Version: 2.4
2
2
  Name: foxes
3
- Version: 1.3
3
+ Version: 1.5
4
4
  Summary: Farm Optimization and eXtended yield Evaluation Software
5
5
  Author: Jonas Schulte
6
6
  Maintainer: Jonas Schulte
@@ -36,7 +36,6 @@ Classifier: Topic :: Scientific/Engineering
36
36
  Classifier: Intended Audience :: Developers
37
37
  Classifier: Intended Audience :: Science/Research
38
38
  Classifier: Programming Language :: Python :: 3
39
- Classifier: Programming Language :: Python :: 3.8
40
39
  Classifier: Programming Language :: Python :: 3.9
41
40
  Classifier: Programming Language :: Python :: 3.10
42
41
  Classifier: Programming Language :: Python :: 3.11
@@ -45,63 +44,42 @@ Classifier: Programming Language :: Python :: 3.13
45
44
  Classifier: License :: OSI Approved :: MIT License
46
45
  Classifier: Operating System :: OS Independent
47
46
  Classifier: Development Status :: 4 - Beta
48
- Requires-Python: >=3.8
47
+ Requires-Python: >=3.9
49
48
  Description-Content-Type: text/markdown
50
49
  License-File: LICENSE
51
- Requires-Dist: matplotlib
52
- Requires-Dist: numpy
53
- Requires-Dist: pandas
54
- Requires-Dist: xarray
55
- Requires-Dist: scipy
56
- Requires-Dist: cycler
57
- Requires-Dist: tqdm
58
- Requires-Dist: pyyaml
50
+ Requires-Dist: cycler>=0.10
51
+ Requires-Dist: h5netcdf>=1.0
52
+ Requires-Dist: matplotlib>=3.8
53
+ Requires-Dist: numpy>=1.26
54
+ Requires-Dist: pandas>=2.0
55
+ Requires-Dist: pyyaml>=4.0
56
+ Requires-Dist: scipy>=1.12
57
+ Requires-Dist: tqdm>=2.0
58
+ Requires-Dist: xarray>=2023
59
59
  Provides-Extra: opt
60
- Requires-Dist: foxes-opt; extra == "opt"
60
+ Requires-Dist: foxes-opt>=0.5; extra == "opt"
61
61
  Provides-Extra: dask
62
- Requires-Dist: h5netcdf; extra == "dask"
63
- Requires-Dist: dask; extra == "dask"
64
- Requires-Dist: distributed; extra == "dask"
65
- Requires-Dist: dask-jobqueue; extra == "dask"
66
- Requires-Dist: setuptools; extra == "dask"
67
- Provides-Extra: eng
68
- Requires-Dist: h5netcdf; extra == "eng"
69
- Requires-Dist: multiprocess; extra == "eng"
70
- Requires-Dist: dask; extra == "eng"
71
- Requires-Dist: distributed; extra == "eng"
72
- Requires-Dist: dask-jobqueue; extra == "eng"
73
- Requires-Dist: setuptools; extra == "eng"
74
- Requires-Dist: mpi4py; extra == "eng"
75
- Requires-Dist: ray; extra == "eng"
76
- Provides-Extra: eng0
77
- Requires-Dist: h5netcdf; extra == "eng0"
78
- Requires-Dist: multiprocess; extra == "eng0"
79
- Requires-Dist: dask; extra == "eng0"
80
- Requires-Dist: distributed; extra == "eng0"
81
- Requires-Dist: dask-jobqueue; extra == "eng0"
82
- Requires-Dist: setuptools; extra == "eng0"
83
- Requires-Dist: ray; extra == "eng0"
84
- Provides-Extra: test
85
- Requires-Dist: flake8; extra == "test"
86
- Requires-Dist: pytest; extra == "test"
87
- Requires-Dist: h5netcdf; extra == "test"
62
+ Requires-Dist: dask>=2022.0; extra == "dask"
63
+ Requires-Dist: distributed>=2022.0; extra == "dask"
64
+ Requires-Dist: dask-jobqueue>=0.8; extra == "dask"
65
+ Requires-Dist: setuptools>=61.0; extra == "dask"
88
66
  Provides-Extra: doc
89
- Requires-Dist: setuptools; extra == "doc"
90
- Requires-Dist: sphinx; extra == "doc"
91
- Requires-Dist: sphinx-immaterial; extra == "doc"
92
- Requires-Dist: nbsphinx; extra == "doc"
93
- Requires-Dist: ipykernel; extra == "doc"
94
- Requires-Dist: ipywidgets; extra == "doc"
95
- Requires-Dist: m2r2; extra == "doc"
96
- Requires-Dist: lxml_html_clean; extra == "doc"
97
- Requires-Dist: dask; extra == "doc"
98
- Requires-Dist: distributed; extra == "doc"
99
- Provides-Extra: dev
100
- Requires-Dist: flake8; extra == "dev"
101
- Requires-Dist: pytest; extra == "dev"
102
- Requires-Dist: jupyter; extra == "dev"
103
- Requires-Dist: objsize; extra == "dev"
104
- Requires-Dist: black[jupyter]; extra == "dev"
67
+ Requires-Dist: setuptools>=61.0; extra == "doc"
68
+ Requires-Dist: sphinx>=5.0; extra == "doc"
69
+ Requires-Dist: sphinx-immaterial>=0.10; extra == "doc"
70
+ Requires-Dist: nbsphinx>=0.5; extra == "doc"
71
+ Requires-Dist: ipykernel>=5.0; extra == "doc"
72
+ Requires-Dist: ipywidgets>=5.0; extra == "doc"
73
+ Requires-Dist: m2r2>=0.2; extra == "doc"
74
+ Requires-Dist: lxml_html_clean>=0.4; extra == "doc"
75
+ Requires-Dist: dask>=2022.0; extra == "doc"
76
+ Requires-Dist: distributed>=2022.0; extra == "doc"
77
+ Provides-Extra: test
78
+ Requires-Dist: flake8>=0.1; extra == "test"
79
+ Requires-Dist: pytest>=7.0; extra == "test"
80
+ Provides-Extra: utils
81
+ Requires-Dist: objsize>=0.5; extra == "utils"
82
+ Dynamic: license-file
105
83
 
106
84
  # Welcome to foxes
107
85
 
@@ -161,14 +139,7 @@ Evaluation Software"`
161
139
 
162
140
  ## Requirements
163
141
 
164
- The supported Python versions are:
165
-
166
- - `Python 3.8`
167
- - `Python 3.9`
168
- - `Python 3.10`
169
- - `Python 3.11`
170
- - `Python 3.12`
171
- - `Python 3.13`
142
+ The supported Python versions are `Python 3.9`...`3.13`.
172
143
 
173
144
  ## Installation
174
145