foxes 0.8.2__py3-none-any.whl → 1.1.0.2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of foxes might be problematic. Click here for more details.

Files changed (215) hide show
  1. docs/source/conf.py +353 -0
  2. examples/abl_states/run.py +160 -0
  3. examples/compare_rotors_pwakes/run.py +217 -0
  4. examples/compare_wakes/run.py +241 -0
  5. examples/dyn_wakes/run.py +311 -0
  6. examples/field_data_nc/run.py +121 -0
  7. examples/induction/run.py +201 -0
  8. examples/multi_height/run.py +113 -0
  9. examples/power_mask/run.py +249 -0
  10. examples/random_timeseries/run.py +210 -0
  11. examples/scan_row/run.py +193 -0
  12. examples/sector_management/run.py +162 -0
  13. examples/sequential/run.py +209 -0
  14. examples/single_state/run.py +201 -0
  15. examples/states_lookup_table/run.py +137 -0
  16. examples/streamline_wakes/run.py +138 -0
  17. examples/tab_file/run.py +142 -0
  18. examples/timelines/run.py +267 -0
  19. examples/timeseries/run.py +190 -0
  20. examples/timeseries_slurm/run.py +185 -0
  21. examples/wind_rose/run.py +141 -0
  22. examples/windio/run.py +29 -0
  23. examples/yawed_wake/run.py +196 -0
  24. foxes/__init__.py +4 -8
  25. foxes/algorithms/__init__.py +1 -1
  26. foxes/algorithms/downwind/downwind.py +247 -111
  27. foxes/algorithms/downwind/models/farm_wakes_calc.py +12 -7
  28. foxes/algorithms/downwind/models/init_farm_data.py +2 -2
  29. foxes/algorithms/downwind/models/point_wakes_calc.py +6 -7
  30. foxes/algorithms/downwind/models/reorder_farm_output.py +1 -2
  31. foxes/algorithms/downwind/models/set_amb_farm_results.py +1 -1
  32. foxes/algorithms/downwind/models/set_amb_point_results.py +5 -3
  33. foxes/algorithms/iterative/iterative.py +74 -34
  34. foxes/algorithms/iterative/models/farm_wakes_calc.py +12 -7
  35. foxes/algorithms/iterative/models/urelax.py +3 -3
  36. foxes/algorithms/sequential/models/plugin.py +5 -5
  37. foxes/algorithms/sequential/models/seq_state.py +1 -1
  38. foxes/algorithms/sequential/sequential.py +126 -255
  39. foxes/constants.py +22 -7
  40. foxes/core/__init__.py +1 -0
  41. foxes/core/algorithm.py +632 -147
  42. foxes/core/data.py +252 -20
  43. foxes/core/data_calc_model.py +15 -291
  44. foxes/core/engine.py +640 -0
  45. foxes/core/farm_controller.py +38 -10
  46. foxes/core/farm_data_model.py +16 -1
  47. foxes/core/ground_model.py +2 -2
  48. foxes/core/model.py +249 -182
  49. foxes/core/partial_wakes_model.py +1 -1
  50. foxes/core/point_data_model.py +17 -2
  51. foxes/core/rotor_model.py +27 -21
  52. foxes/core/states.py +17 -1
  53. foxes/core/turbine_type.py +28 -0
  54. foxes/core/wake_frame.py +30 -34
  55. foxes/core/wake_model.py +5 -5
  56. foxes/core/wake_superposition.py +1 -1
  57. foxes/data/windio/windio_5turbines_timeseries.yaml +31 -15
  58. foxes/engines/__init__.py +17 -0
  59. foxes/engines/dask.py +982 -0
  60. foxes/engines/default.py +75 -0
  61. foxes/engines/futures.py +72 -0
  62. foxes/engines/mpi.py +38 -0
  63. foxes/engines/multiprocess.py +71 -0
  64. foxes/engines/numpy.py +167 -0
  65. foxes/engines/pool.py +249 -0
  66. foxes/engines/ray.py +79 -0
  67. foxes/engines/single.py +141 -0
  68. foxes/input/farm_layout/__init__.py +1 -0
  69. foxes/input/farm_layout/from_csv.py +4 -0
  70. foxes/input/farm_layout/from_json.py +2 -2
  71. foxes/input/farm_layout/grid.py +2 -2
  72. foxes/input/farm_layout/ring.py +65 -0
  73. foxes/input/farm_layout/row.py +2 -2
  74. foxes/input/states/__init__.py +7 -0
  75. foxes/input/states/create/random_abl_states.py +1 -1
  76. foxes/input/states/field_data_nc.py +158 -33
  77. foxes/input/states/multi_height.py +128 -14
  78. foxes/input/states/one_point_flow.py +577 -0
  79. foxes/input/states/scan_ws.py +74 -3
  80. foxes/input/states/single.py +1 -1
  81. foxes/input/states/slice_data_nc.py +681 -0
  82. foxes/input/states/states_table.py +204 -35
  83. foxes/input/windio/__init__.py +2 -2
  84. foxes/input/windio/get_states.py +44 -23
  85. foxes/input/windio/read_attributes.py +48 -17
  86. foxes/input/windio/read_farm.py +116 -102
  87. foxes/input/windio/read_fields.py +16 -6
  88. foxes/input/windio/read_outputs.py +71 -24
  89. foxes/input/windio/runner.py +31 -17
  90. foxes/input/windio/windio.py +41 -23
  91. foxes/models/farm_models/turbine2farm.py +1 -1
  92. foxes/models/ground_models/wake_mirror.py +10 -6
  93. foxes/models/model_book.py +58 -20
  94. foxes/models/partial_wakes/axiwake.py +3 -3
  95. foxes/models/partial_wakes/rotor_points.py +3 -3
  96. foxes/models/partial_wakes/top_hat.py +2 -2
  97. foxes/models/point_models/set_uniform_data.py +1 -1
  98. foxes/models/point_models/tke2ti.py +1 -1
  99. foxes/models/point_models/wake_deltas.py +1 -1
  100. foxes/models/rotor_models/centre.py +4 -0
  101. foxes/models/rotor_models/grid.py +24 -25
  102. foxes/models/rotor_models/levels.py +4 -5
  103. foxes/models/turbine_models/calculator.py +4 -6
  104. foxes/models/turbine_models/kTI_model.py +22 -6
  105. foxes/models/turbine_models/lookup_table.py +30 -4
  106. foxes/models/turbine_models/rotor_centre_calc.py +4 -3
  107. foxes/models/turbine_models/set_farm_vars.py +103 -34
  108. foxes/models/turbine_types/PCt_file.py +27 -3
  109. foxes/models/turbine_types/PCt_from_two.py +27 -3
  110. foxes/models/turbine_types/TBL_file.py +80 -0
  111. foxes/models/turbine_types/__init__.py +2 -0
  112. foxes/models/turbine_types/lookup.py +316 -0
  113. foxes/models/turbine_types/null_type.py +51 -1
  114. foxes/models/turbine_types/wsrho2PCt_from_two.py +29 -5
  115. foxes/models/turbine_types/wsti2PCt_from_two.py +31 -7
  116. foxes/models/vertical_profiles/__init__.py +1 -1
  117. foxes/models/vertical_profiles/data_profile.py +1 -1
  118. foxes/models/wake_frames/__init__.py +1 -0
  119. foxes/models/wake_frames/dynamic_wakes.py +424 -0
  120. foxes/models/wake_frames/farm_order.py +25 -5
  121. foxes/models/wake_frames/rotor_wd.py +6 -4
  122. foxes/models/wake_frames/seq_dynamic_wakes.py +61 -74
  123. foxes/models/wake_frames/streamlines.py +21 -22
  124. foxes/models/wake_frames/timelines.py +330 -129
  125. foxes/models/wake_frames/yawed_wakes.py +7 -4
  126. foxes/models/wake_models/dist_sliced.py +2 -4
  127. foxes/models/wake_models/induction/rankine_half_body.py +5 -5
  128. foxes/models/wake_models/induction/rathmann.py +78 -24
  129. foxes/models/wake_models/induction/self_similar.py +78 -28
  130. foxes/models/wake_models/induction/vortex_sheet.py +86 -48
  131. foxes/models/wake_models/ti/crespo_hernandez.py +6 -4
  132. foxes/models/wake_models/ti/iec_ti.py +40 -21
  133. foxes/models/wake_models/top_hat.py +1 -1
  134. foxes/models/wake_models/wind/bastankhah14.py +8 -6
  135. foxes/models/wake_models/wind/bastankhah16.py +17 -16
  136. foxes/models/wake_models/wind/jensen.py +4 -3
  137. foxes/models/wake_models/wind/turbopark.py +16 -13
  138. foxes/models/wake_superpositions/ti_linear.py +1 -1
  139. foxes/models/wake_superpositions/ti_max.py +1 -1
  140. foxes/models/wake_superpositions/ti_pow.py +1 -1
  141. foxes/models/wake_superpositions/ti_quadratic.py +1 -1
  142. foxes/models/wake_superpositions/ws_linear.py +8 -7
  143. foxes/models/wake_superpositions/ws_max.py +8 -7
  144. foxes/models/wake_superpositions/ws_pow.py +8 -7
  145. foxes/models/wake_superpositions/ws_product.py +5 -5
  146. foxes/models/wake_superpositions/ws_quadratic.py +8 -7
  147. foxes/output/__init__.py +4 -1
  148. foxes/output/farm_layout.py +16 -12
  149. foxes/output/farm_results_eval.py +1 -1
  150. foxes/output/flow_plots_2d/__init__.py +0 -1
  151. foxes/output/flow_plots_2d/flow_plots.py +70 -30
  152. foxes/output/grids.py +92 -22
  153. foxes/output/results_writer.py +2 -2
  154. foxes/output/rose_plot.py +3 -3
  155. foxes/output/seq_plugins/__init__.py +2 -0
  156. foxes/output/{flow_plots_2d → seq_plugins}/seq_flow_ani_plugin.py +64 -22
  157. foxes/output/seq_plugins/seq_wake_debug_plugin.py +145 -0
  158. foxes/output/slice_data.py +131 -111
  159. foxes/output/state_turbine_map.py +19 -14
  160. foxes/output/state_turbine_table.py +19 -19
  161. foxes/utils/__init__.py +1 -1
  162. foxes/utils/abl/neutral.py +2 -2
  163. foxes/utils/abl/stable.py +2 -2
  164. foxes/utils/abl/unstable.py +2 -2
  165. foxes/utils/data_book.py +1 -1
  166. foxes/utils/dev_utils.py +42 -0
  167. foxes/utils/dict.py +24 -1
  168. foxes/utils/exec_python.py +1 -1
  169. foxes/utils/factory.py +176 -53
  170. foxes/utils/geom2d/circle.py +1 -1
  171. foxes/utils/geom2d/polygon.py +1 -1
  172. foxes/utils/geopandas_utils.py +2 -2
  173. foxes/utils/load.py +2 -2
  174. foxes/utils/pandas_helpers.py +3 -2
  175. foxes/utils/wind_dir.py +0 -2
  176. foxes/utils/xarray_utils.py +24 -14
  177. foxes/variables.py +39 -2
  178. {foxes-0.8.2.dist-info → foxes-1.1.0.2.dist-info}/METADATA +75 -33
  179. foxes-1.1.0.2.dist-info/RECORD +309 -0
  180. {foxes-0.8.2.dist-info → foxes-1.1.0.2.dist-info}/WHEEL +1 -1
  181. foxes-1.1.0.2.dist-info/top_level.txt +4 -0
  182. tests/0_consistency/iterative/test_iterative.py +92 -0
  183. tests/0_consistency/partial_wakes/test_partial_wakes.py +90 -0
  184. tests/1_verification/flappy_0_6/PCt_files/flappy/run.py +85 -0
  185. tests/1_verification/flappy_0_6/PCt_files/test_PCt_files.py +103 -0
  186. tests/1_verification/flappy_0_6/abl_states/flappy/run.py +85 -0
  187. tests/1_verification/flappy_0_6/abl_states/test_abl_states.py +87 -0
  188. tests/1_verification/flappy_0_6/partial_top_hat/flappy/run.py +82 -0
  189. tests/1_verification/flappy_0_6/partial_top_hat/test_partial_top_hat.py +82 -0
  190. tests/1_verification/flappy_0_6/row_Jensen_linear_centre/flappy/run.py +92 -0
  191. tests/1_verification/flappy_0_6/row_Jensen_linear_centre/test_row_Jensen_linear_centre.py +93 -0
  192. tests/1_verification/flappy_0_6/row_Jensen_linear_tophat/flappy/run.py +92 -0
  193. tests/1_verification/flappy_0_6/row_Jensen_linear_tophat/test_row_Jensen_linear_tophat.py +96 -0
  194. tests/1_verification/flappy_0_6/row_Jensen_linear_tophat_IECTI2005/flappy/run.py +94 -0
  195. tests/1_verification/flappy_0_6/row_Jensen_linear_tophat_IECTI2005/test_row_Jensen_linear_tophat_IECTI_2005.py +122 -0
  196. tests/1_verification/flappy_0_6/row_Jensen_linear_tophat_IECTI2019/flappy/run.py +94 -0
  197. tests/1_verification/flappy_0_6/row_Jensen_linear_tophat_IECTI2019/test_row_Jensen_linear_tophat_IECTI_2019.py +122 -0
  198. tests/1_verification/flappy_0_6/row_Jensen_quadratic_centre/flappy/run.py +92 -0
  199. tests/1_verification/flappy_0_6/row_Jensen_quadratic_centre/test_row_Jensen_quadratic_centre.py +93 -0
  200. tests/1_verification/flappy_0_6_2/grid_rotors/flappy/run.py +85 -0
  201. tests/1_verification/flappy_0_6_2/grid_rotors/test_grid_rotors.py +130 -0
  202. tests/1_verification/flappy_0_6_2/row_Bastankhah_Crespo/flappy/run.py +96 -0
  203. tests/1_verification/flappy_0_6_2/row_Bastankhah_Crespo/test_row_Bastankhah_Crespo.py +116 -0
  204. tests/1_verification/flappy_0_6_2/row_Bastankhah_linear_centre/flappy/run.py +93 -0
  205. tests/1_verification/flappy_0_6_2/row_Bastankhah_linear_centre/test_row_Bastankhah_linear_centre.py +99 -0
  206. tests/3_examples/test_examples.py +34 -0
  207. foxes/VERSION +0 -1
  208. foxes/output/flow_plots_2d.py +0 -0
  209. foxes/utils/geopandas_helpers.py +0 -294
  210. foxes/utils/runners/__init__.py +0 -1
  211. foxes/utils/runners/runners.py +0 -280
  212. foxes-0.8.2.dist-info/RECORD +0 -247
  213. foxes-0.8.2.dist-info/top_level.txt +0 -1
  214. foxes-0.8.2.dist-info/zip-safe +0 -1
  215. {foxes-0.8.2.dist-info → foxes-1.1.0.2.dist-info}/LICENSE +0 -0
@@ -26,7 +26,7 @@ class PCtFromTwo(TurbineType):
26
26
  col_ct: str
27
27
  The ct column
28
28
  rho: float
29
- The air densitiy for which the data is valid
29
+ The air density for which the data is valid
30
30
  or None for no correction
31
31
  WSCT: str
32
32
  The wind speed variable for ct lookup
@@ -76,7 +76,7 @@ class PCtFromTwo(TurbineType):
76
76
  col_ct: str
77
77
  The ct column
78
78
  rho: float, optional
79
- The air densitiy for which the data is valid
79
+ The air density for which the data is valid
80
80
  or None for no correction
81
81
  p_ct: float
82
82
  The exponent for yaw dependency of ct
@@ -126,6 +126,30 @@ class PCtFromTwo(TurbineType):
126
126
  a += f", var_ws_ct={self.WSCT}, var_ws_P={self.WSP}"
127
127
  return f"{type(self).__name__}({a})"
128
128
 
129
+ def needs_rews2(self):
130
+ """
131
+ Returns flag for requiring REWS2 variable
132
+
133
+ Returns
134
+ -------
135
+ flag: bool
136
+ True if REWS2 is required
137
+
138
+ """
139
+ return self.WSCT == FV.REWS2 or self.WSP == FV.REWS2
140
+
141
+ def needs_rews3(self):
142
+ """
143
+ Returns flag for requiring REWS3 variable
144
+
145
+ Returns
146
+ -------
147
+ flag: bool
148
+ True if REWS3 is required
149
+
150
+ """
151
+ return self.WSCT == FV.REWS3 or self.WSP == FV.REWS3
152
+
129
153
  def output_farm_vars(self, algo):
130
154
  """
131
155
  The variables which are being modified by the model.
@@ -289,7 +313,7 @@ class PCtFromTwo(TurbineType):
289
313
  super().modify_cutin(modify_ct, modify_P)
290
314
 
291
315
  def calculate(self, algo, mdata, fdata, st_sel):
292
- """ "
316
+ """
293
317
  The main model calculation.
294
318
 
295
319
  This function is executed on a single chunk of data,
@@ -0,0 +1,80 @@
1
+ import numpy as np
2
+ import pandas as pd
3
+ from pathlib import Path
4
+
5
+ from .PCt_file import PCtFile
6
+ from foxes.data import parse_Pct_file_name
7
+ import foxes.constants as FC
8
+
9
+
10
+ class TBLFile(PCtFile):
11
+ """
12
+ Reads turbine data from a TBL file.
13
+
14
+ Examples
15
+ --------
16
+ A TBL file is a csv file with space as separator
17
+ and two header lines. The followind lines denote
18
+ wind speed, ct, P.
19
+
20
+ - first row will be ignored
21
+ - second row: H D ct-stand-still rated-power-in-MW
22
+ - further rows: ws ct P-in-kW
23
+
24
+ For example:
25
+
26
+ 45
27
+ 175.0 290.0 0.03 22.0
28
+ 3.0 0.820 102.9
29
+ 3.5 0.800 444.0
30
+ 4.0 0.810 874.7
31
+ 4.5 0.820 1418.7
32
+ 5.0 0.820 2100.9
33
+ 5.5 0.830 3021.2
34
+ 6.0 0.830 3904.7
35
+ 6.5 0.830 5061.7
36
+ 7.0 0.810 6379.0
37
+
38
+ :group: models.turbine_types
39
+
40
+ """
41
+
42
+ def __init__(
43
+ self,
44
+ tbl_file,
45
+ rho=1.225,
46
+ **parameters,
47
+ ):
48
+ """
49
+ Constructor.
50
+
51
+ Parameters
52
+ ----------
53
+ tbl_file: str
54
+ Path to the tbl file
55
+ rho: float
56
+ The air density for the curves
57
+ paramerers: dict, optional
58
+ Additional parameters for PCtFile class
59
+
60
+ """
61
+ fpath = Path(tbl_file)
62
+ assert fpath.suffix == ".tbl", f"Expecting *.tbl file, got '{tbl_file}'"
63
+
64
+ meta = np.genfromtxt(fpath, skip_header=1, max_rows=1)
65
+ sdata = pd.read_csv(
66
+ fpath, sep=" ", skiprows=2, header=None, names=["ws", "ct", "P"]
67
+ )
68
+
69
+ super().__init__(
70
+ sdata,
71
+ col_ws="ws",
72
+ col_P="P",
73
+ col_ct="ct",
74
+ H=meta[0],
75
+ D=meta[1],
76
+ P_nominal=meta[3] * 1e3,
77
+ P_unit="kW",
78
+ rho=rho,
79
+ **parameters,
80
+ )
@@ -9,3 +9,5 @@ from .CpCt_from_two import CpCtFromTwo
9
9
  from .null_type import NullType
10
10
  from .wsrho2PCt_from_two import WsRho2PCtFromTwo
11
11
  from .wsti2PCt_from_two import WsTI2PCtFromTwo
12
+ from .lookup import FromLookupTable
13
+ from .TBL_file import TBLFile
@@ -0,0 +1,316 @@
1
+ import numpy as np
2
+ import pandas as pd
3
+
4
+ from foxes.core import TurbineType, FData
5
+ from foxes.data import parse_Pct_file_name
6
+ from foxes.models.turbine_models import LookupTable
7
+ import foxes.variables as FV
8
+
9
+
10
+ class FromLookupTable(TurbineType):
11
+ """
12
+ Calculate power and ct by interpolating
13
+ by using a lookup-table
14
+
15
+ Attributes
16
+ ----------
17
+ source: str or pandas.DataFrame
18
+ The file path, static name, or data
19
+ rho: float
20
+ The air density for which the data is valid
21
+ or None for no correction
22
+ WSCT: str
23
+ The wind speed variable for ct lookup
24
+ WSP: str
25
+ The wind speed variable for power lookup
26
+ rpars: dict, optional
27
+ Parameters for pandas file reading
28
+
29
+ :group: models.turbine_types
30
+
31
+ """
32
+
33
+ def __init__(
34
+ self,
35
+ data_source,
36
+ input_vars,
37
+ varmap={},
38
+ lookup_pars={},
39
+ rho=None,
40
+ p_ct=1.0,
41
+ p_P=1.88,
42
+ var_ws_ct=FV.REWS2,
43
+ var_ws_P=FV.REWS3,
44
+ pd_file_read_pars={},
45
+ interpn_args={},
46
+ **parameters,
47
+ ):
48
+ """
49
+ Constructor.
50
+
51
+ Parameters
52
+ ----------
53
+ data_source: str or pandas.DataFrame
54
+ The file path, static name, or data
55
+ input_vars: list of str
56
+ The foxes input variables
57
+ varmap: dict
58
+ Mapping from foxes variable names
59
+ to column names in the data_source
60
+ lookup_pars: dict
61
+ Additional parameters for the LookupTable model
62
+ rho: float, optional
63
+ The air density for which the data is valid
64
+ or None for no correction
65
+ p_ct: float
66
+ The exponent for yaw dependency of ct
67
+ p_P: float
68
+ The exponent for yaw dependency of P
69
+ var_ws_ct: str
70
+ The wind speed variable for ct lookup
71
+ var_ws_P: str
72
+ The wind speed variable for power lookup
73
+ pd_file_read_pars: dict
74
+ Parameters for pandas file reading
75
+ interpn_args: dict
76
+ Parameters for scipy intern or interp1d
77
+ parameters: dict, optional
78
+ Additional parameters for TurbineType class
79
+
80
+ """
81
+ if not isinstance(data_source, pd.DataFrame):
82
+ pars = parse_Pct_file_name(data_source)
83
+ pars.update(parameters)
84
+ else:
85
+ pars = parameters
86
+
87
+ super().__init__(**pars)
88
+
89
+ self.source = data_source
90
+ self.rho = rho
91
+ self.p_ct = p_ct
92
+ self.p_P = p_P
93
+ self.WSCT = var_ws_ct
94
+ self.WSP = var_ws_P
95
+ self.rpars = pd_file_read_pars
96
+
97
+ if FV.REWS not in input_vars or len(
98
+ set(input_vars).intersection([FV.WS, FV.REWS2, FV.REWS3])
99
+ ):
100
+ raise KeyError(
101
+ f"Turbine type '{self.name}': Expecting '{FV.REWS}' as wind speed variable in inputv_vars, got {input_vars}"
102
+ )
103
+
104
+ iargs = dict(bounds_error=False, fill_value=0)
105
+ iargs.update(interpn_args)
106
+ self._lookup = LookupTable(
107
+ data_source=data_source,
108
+ input_vars=input_vars,
109
+ output_vars=[FV.P, FV.CT],
110
+ varmap=varmap,
111
+ interpn_args=iargs,
112
+ **lookup_pars,
113
+ )
114
+
115
+ def __repr__(self):
116
+ a = f"D={self.D}, H={self.H}, P_nominal={self.P_nominal}, P_unit={self.P_unit}, rho={self.rho}"
117
+ a += f", var_ws_ct={self.WSCT}, var_ws_P={self.WSP}"
118
+ return f"{type(self).__name__}({a})"
119
+
120
+ def needs_rews2(self):
121
+ """
122
+ Returns flag for requiring REWS2 variable
123
+
124
+ Returns
125
+ -------
126
+ flag: bool
127
+ True if REWS2 is required
128
+
129
+ """
130
+ return self.WSCT == FV.REWS2 or self.WSP == FV.REWS2
131
+
132
+ def needs_rews3(self):
133
+ """
134
+ Returns flag for requiring REWS3 variable
135
+
136
+ Returns
137
+ -------
138
+ flag: bool
139
+ True if REWS3 is required
140
+
141
+ """
142
+ return self.WSCT == FV.REWS3 or self.WSP == FV.REWS3
143
+
144
+ def sub_models(self):
145
+ """
146
+ List of all sub-models
147
+
148
+ Returns
149
+ -------
150
+ smdls: list of foxes.core.Model
151
+ All sub models
152
+
153
+ """
154
+ return [self._lookup]
155
+
156
+ def output_farm_vars(self, algo):
157
+ """
158
+ The variables which are being modified by the model.
159
+
160
+ Parameters
161
+ ----------
162
+ algo: foxes.core.Algorithm
163
+ The calculation algorithm
164
+
165
+ Returns
166
+ -------
167
+ output_vars: list of str
168
+ The output variable names
169
+
170
+ """
171
+ return [FV.P, FV.CT]
172
+
173
+ def initialize(self, algo, verbosity=0, force=False):
174
+ """
175
+ Initializes the model.
176
+
177
+ Parameters
178
+ ----------
179
+ algo: foxes.core.Algorithm
180
+ The calculation algorithm
181
+ verbosity: int
182
+ The verbosity level, 0 = silent
183
+ force: bool
184
+ Overwrite existing data
185
+
186
+ """
187
+ super().initialize(algo, verbosity, force)
188
+ if self.P_nominal is None:
189
+ col_P = self._lookup.varmap.get(FV.P, FV.P)
190
+ self.P_nominal = np.max(self._lookup._data[col_P].to_numpy())
191
+
192
+ def modify_cutin(
193
+ self,
194
+ modify_ct,
195
+ modify_P,
196
+ steps=20,
197
+ iterations=100,
198
+ a=0.55,
199
+ b=0.55,
200
+ ):
201
+ """
202
+ Modify the data such that a discontinuity
203
+ at cutin wind speed is avoided
204
+
205
+ Parameters
206
+ ----------
207
+ variable: str
208
+ The target variable
209
+ modify_ct: bool
210
+ Flag for modification of the ct curve
211
+ modify_P: bool
212
+ Flag for modification of the power curve
213
+ steps: int
214
+ The number of wind speed steps between 0 and
215
+ the cutin wind speed
216
+ iterations: int
217
+ The number of iterations
218
+ a: float
219
+ Coefficient for iterative mixing
220
+ b: float
221
+ Coefficient for iterative mixing
222
+
223
+ """
224
+ if modify_ct or modify_P:
225
+ raise NotImplementedError
226
+
227
+ else:
228
+ super().modify_cutin(modify_ct, modify_P)
229
+
230
+ def calculate(self, algo, mdata, fdata, st_sel):
231
+ """
232
+ The main model calculation.
233
+
234
+ This function is executed on a single chunk of data,
235
+ all computations should be based on numpy arrays.
236
+
237
+ Parameters
238
+ ----------
239
+ algo: foxes.core.Algorithm
240
+ The calculation algorithm
241
+ mdata: foxes.core.MData
242
+ The model data
243
+ fdata: foxes.core.FData
244
+ The farm data
245
+ st_sel: numpy.ndarray of bool
246
+ The state-turbine selection,
247
+ shape: (n_states, n_turbines)
248
+
249
+ Returns
250
+ -------
251
+ results: dict
252
+ The resulting data, keys: output variable str.
253
+ Values: numpy.ndarray with shape (n_states, n_turbines)
254
+
255
+ """
256
+ # prepare data for lookup:
257
+ input_vars = self._lookup.input_vars
258
+ fdata_lookup = FData(
259
+ data={v: fdata[v] for v in input_vars},
260
+ dims={v: fdata.dims[v] for v in input_vars},
261
+ loop_dims=fdata.loop_dims,
262
+ )
263
+ for v in self.output_farm_vars(algo):
264
+ fdata_lookup.add(v, fdata[v], fdata.dims[v])
265
+
266
+ rews2 = None
267
+ rews3 = None
268
+ if self.WSP != FV.REWS or self.WSCT != FV.REWS:
269
+ rews2 = fdata[self.WSCT].copy()
270
+ rews3 = fdata[self.WSP].copy()
271
+
272
+ # apply air density correction:
273
+ if self.rho is not None:
274
+ if rews2 is None:
275
+ rews2 = fdata[self.WSCT].copy()
276
+ rews3 = fdata[self.WSP].copy()
277
+
278
+ # correct wind speed by air density, such
279
+ # that in the partial load region the
280
+ # correct value is reconstructed:
281
+ rho = fdata[FV.RHO][st_sel]
282
+ rews3[st_sel] *= (self.rho / rho) ** (1.0 / 3.0)
283
+ del rho
284
+
285
+ # in yawed case, calc yaw corrected wind speed:
286
+ if FV.YAWM in fdata and (self.p_P is not None or self.p_ct is not None):
287
+ if rews2 is None:
288
+ rews2 = fdata[self.WSCT].copy()
289
+ rews3 = fdata[self.WSP].copy()
290
+
291
+ # calculate corrected wind speed wsc,
292
+ # gives ws**3 * cos**p_P in partial load region
293
+ # and smoothly deals with full load region:
294
+ yawm = fdata[FV.YAWM][st_sel]
295
+ if np.any(np.isnan(yawm)):
296
+ raise ValueError(
297
+ f"{self.name}: Found NaN values for variable '{FV.YAWM}'. Maybe change order in turbine_models?"
298
+ )
299
+ cosm = np.cos(yawm / 180 * np.pi)
300
+ if self.p_ct is not None:
301
+ rews2[st_sel] *= (cosm**self.p_ct) ** 0.5
302
+ if self.p_P is not None:
303
+ rews3[st_sel] *= (cosm**self.p_P) ** (1.0 / 3.0)
304
+ del yawm, cosm
305
+
306
+ # run lookup:
307
+ if rews2 is None:
308
+ out = self._lookup.calculate(algo, mdata, fdata_lookup, st_sel)
309
+ else:
310
+ fdata_lookup[FV.REWS] = rews2
311
+ ct = self._lookup.calculate(algo, mdata, fdata_lookup, st_sel)[FV.CT]
312
+ fdata_lookup[FV.REWS] = rews3
313
+ out = self._lookup.calculate(algo, mdata, fdata_lookup, st_sel)
314
+ out[FV.CT] = ct
315
+
316
+ return out
@@ -9,6 +9,56 @@ class NullType(TurbineType):
9
9
 
10
10
  """
11
11
 
12
+ def __init__(
13
+ self,
14
+ *args,
15
+ needs_rews2=False,
16
+ needs_rews3=False,
17
+ **kwargs,
18
+ ):
19
+ """
20
+ Constructor.
21
+
22
+ Parameters
23
+ ----------
24
+ args: tuple, optional
25
+ Additional parameters for TurbineType class
26
+ needs_rews2: bool
27
+ Flag for runs that require the REWS2 variable
28
+ needs_rews3: bool
29
+ Flag for runs that require the REWS3 variable
30
+ kwargs: dict, optional
31
+ Additional parameters for TurbineType class
32
+
33
+ """
34
+ super().__init__(*args, **kwargs)
35
+ self._rews2 = needs_rews2
36
+ self._rews3 = needs_rews3
37
+
38
+ def needs_rews2(self):
39
+ """
40
+ Returns flag for requiring REWS2 variable
41
+
42
+ Returns
43
+ -------
44
+ flag: bool
45
+ True if REWS2 is required
46
+
47
+ """
48
+ return self._rews2
49
+
50
+ def needs_rews3(self):
51
+ """
52
+ Returns flag for requiring REWS3 variable
53
+
54
+ Returns
55
+ -------
56
+ flag: bool
57
+ True if REWS3 is required
58
+
59
+ """
60
+ return self._rews3
61
+
12
62
  def output_farm_vars(self, algo):
13
63
  """
14
64
  The variables which are being modified by the model.
@@ -27,7 +77,7 @@ class NullType(TurbineType):
27
77
  return []
28
78
 
29
79
  def calculate(self, algo, mdata, fdata, st_sel):
30
- """ "
80
+ """
31
81
  The main model calculation.
32
82
 
33
83
  This function is executed on a single chunk of data,
@@ -37,9 +37,9 @@ class WsRho2PCtFromTwo(TurbineType):
37
37
  rpars_ct: dict, optional
38
38
  Parameters for pandas ct file reading
39
39
  ipars_P: dict, optional
40
- Parameters for scipy.interpolate.interpn()
40
+ Parameters for scipy.interpolate.interpn
41
41
  ipars_ct: dict, optional
42
- Parameters for scipy.interpolate.interpn()
42
+ Parameters for scipy.interpolate.interpn
43
43
 
44
44
  :group: models.turbine_types
45
45
 
@@ -81,9 +81,9 @@ class WsRho2PCtFromTwo(TurbineType):
81
81
  pd_file_read_pars_ct: dict
82
82
  Parameters for pandas ct file reading
83
83
  interpn_pars_P: dict, optional
84
- Parameters for scipy.interpolate.interpn()
84
+ Parameters for scipy.interpolate.interpn
85
85
  interpn_pars_ct: dict, optional
86
- Parameters for scipy.interpolate.interpn()
86
+ Parameters for scipy.interpolate.interpn
87
87
  parameters: dict, optional
88
88
  Additional parameters for TurbineType class
89
89
 
@@ -115,6 +115,30 @@ class WsRho2PCtFromTwo(TurbineType):
115
115
  self._P = None
116
116
  self._ct = None
117
117
 
118
+ def needs_rews2(self):
119
+ """
120
+ Returns flag for requiring REWS2 variable
121
+
122
+ Returns
123
+ -------
124
+ flag: bool
125
+ True if REWS2 is required
126
+
127
+ """
128
+ return self.WSCT == FV.REWS2 or self.WSP == FV.REWS2
129
+
130
+ def needs_rews3(self):
131
+ """
132
+ Returns flag for requiring REWS3 variable
133
+
134
+ Returns
135
+ -------
136
+ flag: bool
137
+ True if REWS3 is required
138
+
139
+ """
140
+ return self.WSCT == FV.REWS3 or self.WSP == FV.REWS3
141
+
118
142
  def output_farm_vars(self, algo):
119
143
  """
120
144
  The variables which are being modified by the model.
@@ -205,7 +229,7 @@ class WsRho2PCtFromTwo(TurbineType):
205
229
  print()
206
230
 
207
231
  def calculate(self, algo, mdata, fdata, st_sel):
208
- """ "
232
+ """
209
233
  The main model calculation.
210
234
 
211
235
  This function is executed on a single chunk of data,
@@ -37,11 +37,11 @@ class WsTI2PCtFromTwo(TurbineType):
37
37
  rpars_ct: dict, optional
38
38
  Parameters for pandas ct file reading
39
39
  ipars_P: dict, optional
40
- Parameters for scipy.interpolate.interpn()
40
+ Parameters for scipy.interpolate.interpn
41
41
  ipars_ct: dict, optional
42
- Parameters for scipy.interpolate.interpn()
42
+ Parameters for scipy.interpolate.interpn
43
43
  rho: float
44
- The air densitiy for which the data is valid
44
+ The air density for which the data is valid
45
45
  or None for no correction
46
46
 
47
47
  :group: models.turbine_types
@@ -73,7 +73,7 @@ class WsTI2PCtFromTwo(TurbineType):
73
73
  data_source_ct: str or pandas.DataFrame
74
74
  The file path for the ct curve, static name, or data
75
75
  rho: float, optional
76
- The air densitiy for which the data is valid
76
+ The air density for which the data is valid
77
77
  or None for no correction
78
78
  p_ct: float
79
79
  The exponent for yaw dependency of ct
@@ -88,9 +88,9 @@ class WsTI2PCtFromTwo(TurbineType):
88
88
  pd_file_read_pars_ct: dict
89
89
  Parameters for pandas ct file reading
90
90
  interpn_pars_P: dict, optional
91
- Parameters for scipy.interpolate.interpn()
91
+ Parameters for scipy.interpolate.interpn
92
92
  interpn_pars_ct: dict, optional
93
- Parameters for scipy.interpolate.interpn()
93
+ Parameters for scipy.interpolate.interpn
94
94
  parameters: dict, optional
95
95
  Additional parameters for TurbineType class
96
96
 
@@ -127,6 +127,30 @@ class WsTI2PCtFromTwo(TurbineType):
127
127
  a = f"D={self.D}, H={self.H}, P_nominal={self.P_nominal}, P_unit={self.P_unit}, rho={self.rho}"
128
128
  return f"{type(self).__name__}({a})"
129
129
 
130
+ def needs_rews2(self):
131
+ """
132
+ Returns flag for requiring REWS2 variable
133
+
134
+ Returns
135
+ -------
136
+ flag: bool
137
+ True if REWS2 is required
138
+
139
+ """
140
+ return self.WSCT == FV.REWS2 or self.WSP == FV.REWS2
141
+
142
+ def needs_rews3(self):
143
+ """
144
+ Returns flag for requiring REWS3 variable
145
+
146
+ Returns
147
+ -------
148
+ flag: bool
149
+ True if REWS3 is required
150
+
151
+ """
152
+ return self.WSCT == FV.REWS3 or self.WSP == FV.REWS3
153
+
130
154
  def output_farm_vars(self, algo):
131
155
  """
132
156
  The variables which are being modified by the model.
@@ -217,7 +241,7 @@ class WsTI2PCtFromTwo(TurbineType):
217
241
  print()
218
242
 
219
243
  def calculate(self, algo, mdata, fdata, st_sel):
220
- """ "
244
+ """
221
245
  The main model calculation.
222
246
 
223
247
  This function is executed on a single chunk of data,
@@ -1,5 +1,5 @@
1
1
  """
2
- Verctical profile models.
2
+ Vertical profile models.
3
3
  """
4
4
 
5
5
  from .uniform import UniformProfile
@@ -31,7 +31,7 @@ class DataProfile(VerticalProfile):
31
31
  col_z=None,
32
32
  col_var=None,
33
33
  pd_read_pars={},
34
- **interp_pars
34
+ **interp_pars,
35
35
  ):
36
36
  """
37
37
  Constructor
@@ -8,3 +8,4 @@ from .timelines import Timelines
8
8
  from .yawed_wakes import YawedWakes
9
9
  from .farm_order import FarmOrder
10
10
  from .seq_dynamic_wakes import SeqDynamicWakes
11
+ from .dynamic_wakes import DynamicWakes