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
@@ -0,0 +1,217 @@
1
+ import numpy as np
2
+ import pandas as pd
3
+ import argparse
4
+ import matplotlib.pyplot as plt
5
+
6
+ import foxes
7
+ import foxes.variables as FV
8
+
9
+
10
+ def calc(args, rotor, sdata, pwake):
11
+ mbook = foxes.models.ModelBook()
12
+ ttype = foxes.models.turbine_types.PCtFile(args.turbine_file)
13
+ mbook.turbine_types[ttype.name] = ttype
14
+ D = ttype.D
15
+
16
+ farm = foxes.WindFarm()
17
+ farm.add_turbine(
18
+ foxes.Turbine(
19
+ xy=np.array([0.0, 0.0]), turbine_models=args.tmodels + [ttype.name]
20
+ ),
21
+ verbosity=0,
22
+ )
23
+ farm.add_turbine(
24
+ foxes.Turbine(
25
+ xy=np.array([args.dist_x, 0.0]),
26
+ turbine_models=["sety"] + args.tmodels + [ttype.name],
27
+ ),
28
+ verbosity=0,
29
+ )
30
+
31
+ states = foxes.input.states.StatesTable(
32
+ sdata,
33
+ output_vars=[FV.WS, FV.WD, FV.TI, FV.RHO],
34
+ var2col={FV.WS: "ws", FV.WD: "wd", FV.TI: "ti", FV.RHO: "rho"},
35
+ )
36
+
37
+ ydata = np.full((len(sdata.index), farm.n_turbines), np.nan)
38
+ ydata[:, 1] = sdata["y"].to_numpy()
39
+ mbook.turbine_models["sety"] = foxes.models.turbine_models.SetFarmVars(
40
+ pre_rotor=True
41
+ )
42
+ mbook.turbine_models["sety"].add_var(FV.Y, ydata)
43
+
44
+ algo = foxes.algorithms.Downwind(
45
+ farm,
46
+ states,
47
+ wake_models=args.wakes,
48
+ rotor_model=rotor,
49
+ wake_frame="rotor_wd",
50
+ partial_wakes=pwake,
51
+ mbook=mbook,
52
+ verbosity=0,
53
+ )
54
+
55
+ print(f"\nCalculating rotor = {rotor}, pwake = {pwake}")
56
+ farm_results = algo.calc_farm()
57
+
58
+ return farm_results, D
59
+
60
+
61
+ if __name__ == "__main__":
62
+ parser = argparse.ArgumentParser()
63
+ parser.add_argument("--ws", help="The wind speed", type=float, default=9.0)
64
+ parser.add_argument("--wd", help="The wind direction", type=float, default=270.0)
65
+ parser.add_argument("--ti", help="The TI value", type=float, default=0.08)
66
+ parser.add_argument("--rho", help="The air density", type=float, default=1.225)
67
+ parser.add_argument(
68
+ "-t",
69
+ "--turbine_file",
70
+ help="The P-ct-curve csv file (path or static)",
71
+ default="NREL-5MW-D126-H90.csv",
72
+ )
73
+ parser.add_argument("-v", "--var", help="The variable selection", default=FV.REWS)
74
+ parser.add_argument(
75
+ "-d", "--dist_x", help="The turbine distance in x", type=float, default=500.0
76
+ )
77
+ parser.add_argument(
78
+ "-y0", "--ymin", help="The minimal y value", type=float, default=-500.0
79
+ )
80
+ parser.add_argument(
81
+ "-y1", "--ymax", help="The maximal y value", type=float, default=500.0
82
+ )
83
+ parser.add_argument(
84
+ "-ys", "--ystep", help="The step size in y direction", type=float, default=1.0
85
+ )
86
+ parser.add_argument(
87
+ "-w",
88
+ "--wakes",
89
+ help="The wake models",
90
+ default=["Bastankhah2014_linear_k002"],
91
+ nargs="+",
92
+ )
93
+ parser.add_argument(
94
+ "-m", "--tmodels", help="The turbine models", default=["kTI_02"], nargs="+"
95
+ )
96
+ parser.add_argument(
97
+ "-r", "--rotors", help="The rotor model(s)", default=["grid400"], nargs="+"
98
+ )
99
+ parser.add_argument(
100
+ "-p",
101
+ "--pwakes",
102
+ help="The partial wakes model(s)",
103
+ default=["grid16", "axiwake6", "rotor_points"],
104
+ nargs="+",
105
+ )
106
+ parser.add_argument("-tt", "--title", help="The figure title", default=None)
107
+ parser.add_argument(
108
+ "-e",
109
+ "--engine",
110
+ help="The engine",
111
+ default="ProcessEngine",
112
+ )
113
+ parser.add_argument(
114
+ "-n", "--n_cpus", help="The number of cpus", default=None, type=int
115
+ )
116
+ parser.add_argument(
117
+ "-c",
118
+ "--chunksize_states",
119
+ help="The chunk size for states",
120
+ default=None,
121
+ type=int,
122
+ )
123
+ parser.add_argument(
124
+ "-C",
125
+ "--chunksize_points",
126
+ help="The chunk size for points",
127
+ default=None,
128
+ type=int,
129
+ )
130
+ parser.add_argument(
131
+ "-nf", "--nofig", help="Do not show figures", action="store_true"
132
+ )
133
+ args = parser.parse_args()
134
+
135
+ ws = args.ws
136
+ var = args.var
137
+ swks = ", ".join(args.wakes)
138
+ ttl0 = f"ws$_0$ = {ws} m, ti$_0$ = {args.ti}"
139
+
140
+ varn = 1
141
+ vlab = var
142
+ if var in [FV.WS, FV.REWS, FV.REWS2, FV.REWS3]:
143
+ varn = ws
144
+ vlab = f"{var}/ws$_0$"
145
+
146
+ Ny = int((args.ymax - args.ymin) // args.ystep)
147
+ sdata = pd.DataFrame(index=range(Ny + 1))
148
+ sdata.index.name = "state"
149
+ sdata["ws"] = args.ws
150
+ sdata["wd"] = args.wd
151
+ sdata["ti"] = args.ti
152
+ sdata["rho"] = args.rho
153
+ sdata["y"] = np.linspace(args.ymin, args.ymax, Ny + 1)
154
+
155
+ fig, ax = plt.subplots(figsize=(10, 4))
156
+ with foxes.Engine.new(
157
+ engine_type=args.engine,
158
+ n_procs=args.n_cpus,
159
+ chunk_size_states=args.chunksize_states,
160
+ chunk_size_points=args.chunksize_points,
161
+ ):
162
+ if len(args.rotors) == 1:
163
+ for pwake in args.pwakes:
164
+ farm_results, D = calc(args, args.rotors[0], sdata, pwake)
165
+
166
+ ax.plot(
167
+ farm_results[FV.Y][:, 1] / D,
168
+ farm_results[var][:, 1] / varn,
169
+ linewidth=2,
170
+ alpha=0.6,
171
+ label=pwake,
172
+ )
173
+
174
+ title = f"{swks}, variable {var}\nVarying partial wake models, {ttl0}, rotor = {args.rotors[0]}"
175
+
176
+ elif len(args.pwakes) == 1:
177
+ for rotor in args.rotors:
178
+ farm_results, D = calc(args, rotor, sdata, args.pwakes[0])
179
+
180
+ ax.plot(
181
+ farm_results[FV.Y][:, 1] / D,
182
+ farm_results[var][:, 1] / varn,
183
+ linewidth=2,
184
+ alpha=0.6,
185
+ label=rotor,
186
+ )
187
+
188
+ title = f"{swks}, variable {var}\nVarying rotor models, {ttl0}, pwake = {args.pwakes[0]}"
189
+
190
+ elif len(args.rotors) == len(args.pwakes):
191
+ for rotor, pwake in zip(args.rotors, args.pwakes):
192
+ farm_results, D = calc(args, rotor, sdata, pwake)
193
+
194
+ ax.plot(
195
+ farm_results[FV.Y][:, 1] / D,
196
+ farm_results[var][:, 1] / varn,
197
+ linewidth=2,
198
+ alpha=0.6,
199
+ label=f"{rotor}, {pwake}",
200
+ )
201
+
202
+ title = "{swks}, variable {var}\nVarying rotor and partial wake models, {ttl0}"
203
+
204
+ else:
205
+ raise ValueError(
206
+ f"Please either give one rotor, or one pwake, or same number of both"
207
+ )
208
+
209
+ if args.title is not None:
210
+ title = args.title
211
+
212
+ ax.set_title(title)
213
+ ax.set_xlabel("y/D")
214
+ ax.set_ylabel(vlab)
215
+ ax.legend()
216
+ if not args.nofig:
217
+ plt.show()
@@ -0,0 +1,241 @@
1
+ import numpy as np
2
+ import argparse
3
+ import matplotlib.pyplot as plt
4
+
5
+ import foxes
6
+ import foxes.variables as FV
7
+
8
+
9
+ def calc(mbook, farm, states, wakes, points, args):
10
+
11
+ algo = foxes.algorithms.Downwind(
12
+ farm,
13
+ states,
14
+ wake_models=wakes,
15
+ rotor_model=args.rotor,
16
+ wake_frame="rotor_wd",
17
+ partial_wakes=args.pwakes,
18
+ mbook=mbook,
19
+ verbosity=0,
20
+ )
21
+
22
+ farm_results = algo.calc_farm()
23
+ point_results = algo.calc_points(farm_results, points[None, :])
24
+
25
+ mbook.finalize(algo, verbosity=0)
26
+
27
+ return point_results[args.var].to_numpy()
28
+
29
+
30
+ if __name__ == "__main__":
31
+ parser = argparse.ArgumentParser()
32
+ parser.add_argument(
33
+ "-d",
34
+ "--dists_D",
35
+ help="turbine distances in units of D",
36
+ type=float,
37
+ nargs="+",
38
+ default=[2.0, 5.0, 8.0, 12.0, 15.0, 20.0],
39
+ )
40
+ parser.add_argument(
41
+ "-y",
42
+ "--span_y",
43
+ help="Span in y direction in units of D",
44
+ type=float,
45
+ default=4,
46
+ )
47
+ parser.add_argument(
48
+ "-sp", "--step", help="Point step size in units of D", type=float, default=0.01
49
+ )
50
+ parser.add_argument(
51
+ "-pc", "--plot_cols", help="Columns in the plot", type=int, default=3
52
+ )
53
+ parser.add_argument(
54
+ "-hg", "--height", help="The point height", type=float, default=None
55
+ )
56
+ parser.add_argument("-v", "--var", help="The plot variable", default=FV.WS)
57
+ parser.add_argument(
58
+ "-fs", "--figsize_scale", help="Scale for single D plot", type=int, default=4
59
+ )
60
+ parser.add_argument("--ws", help="The wind speed", type=float, default=9.0)
61
+ parser.add_argument("--wd", help="The wind direction", type=float, default=270.0)
62
+ parser.add_argument("--ti", help="The TI value", type=float, default=0.05)
63
+ parser.add_argument("--rho", help="The air density", type=float, default=1.225)
64
+ parser.add_argument("--ct", help="Set CT by hand", default=None, type=float)
65
+ parser.add_argument(
66
+ "-t",
67
+ "--turbine_file",
68
+ help="The P-ct-curve csv file (path or static)",
69
+ default="NREL-5MW-D126-H90.csv",
70
+ )
71
+ parser.add_argument(
72
+ "-w",
73
+ "--wakes",
74
+ help="The wake models",
75
+ default=[
76
+ "Bastankhah2014B_linear_k004",
77
+ "Bastankhah2014_linear_k004",
78
+ "Bastankhah2016_linear_k004",
79
+ ],
80
+ nargs="+",
81
+ )
82
+ parser.add_argument(
83
+ "-ew",
84
+ "--ewakes",
85
+ help="The extra wake models",
86
+ default=[],
87
+ nargs="+",
88
+ )
89
+ parser.add_argument(
90
+ "-m", "--tmodels", help="The turbine models", default=[], nargs="+"
91
+ )
92
+ parser.add_argument("-r", "--rotor", help="The rotor model", default="centre")
93
+ parser.add_argument(
94
+ "-p", "--pwakes", help="The partial wakes models", default="centre", nargs="+"
95
+ )
96
+ parser.add_argument(
97
+ "-dfz",
98
+ "--deficit",
99
+ help="Plot the wind deficit instead of wind speed",
100
+ action="store_true",
101
+ )
102
+ parser.add_argument("-e", "--engine", help="The engine", default="ProcessEngine")
103
+ parser.add_argument(
104
+ "-n", "--n_cpus", help="The number of cpus", default=None, type=int
105
+ )
106
+ parser.add_argument(
107
+ "-c",
108
+ "--chunksize_states",
109
+ help="The chunk size for states",
110
+ default=None,
111
+ type=int,
112
+ )
113
+ parser.add_argument(
114
+ "-C",
115
+ "--chunksize_points",
116
+ help="The chunk size for points",
117
+ default=None,
118
+ type=int,
119
+ )
120
+ parser.add_argument(
121
+ "-nf", "--nofig", help="Do not show figures", action="store_true"
122
+ )
123
+ args = parser.parse_args()
124
+
125
+ mbook = foxes.models.ModelBook()
126
+ ttype = foxes.models.turbine_types.PCtFile(args.turbine_file)
127
+ mbook.turbine_types[ttype.name] = ttype
128
+ D = ttype.D
129
+ H = ttype.H
130
+
131
+ models = args.tmodels + [ttype.name]
132
+ if args.ct is not None:
133
+ mbook.turbine_models["set_ct"] = foxes.models.turbine_models.SetFarmVars()
134
+ mbook.turbine_models["set_ct"].add_var(FV.CT, args.ct)
135
+ models.append("set_ct")
136
+
137
+ states = foxes.input.states.SingleStateStates(
138
+ ws=args.ws, wd=args.wd, ti=args.ti, rho=args.rho
139
+ )
140
+
141
+ farm = foxes.WindFarm()
142
+ farm.add_turbine(
143
+ foxes.Turbine(
144
+ xy=np.array([0.0, 0.0]),
145
+ turbine_models=models,
146
+ )
147
+ )
148
+
149
+ # y lines:
150
+
151
+ print("\nCalculating y lines\n")
152
+
153
+ xlist = np.array(args.dists_D) * D
154
+ ylist = np.arange(-args.span_y, args.span_y + args.step, args.step) * D
155
+ nd = len(args.dists_D)
156
+ nx = len(xlist)
157
+ ny = len(ylist)
158
+ points = np.zeros((nd, ny, 3))
159
+ points[:, :, 2] = args.height if args.height is not None else H
160
+ points[:, :, 0] = xlist[:, None]
161
+ points[:, :, 1] = ylist[None, :]
162
+ points = points.reshape(nd * ny, 3)
163
+
164
+ ncols = min(args.plot_cols, nd)
165
+ nrows = int(nd / ncols)
166
+ while nrows * ncols < nd:
167
+ nrows += 1
168
+
169
+ figsize = (ncols * args.figsize_scale, nrows * args.figsize_scale)
170
+ fig, axs = plt.subplots(nrows, ncols, figsize=figsize, sharex=True, sharey=True)
171
+ with foxes.Engine.new(
172
+ engine_type=args.engine,
173
+ n_procs=args.n_cpus,
174
+ chunk_size_states=args.chunksize_states,
175
+ chunk_size_points=args.chunksize_points,
176
+ ):
177
+ for wake in args.wakes:
178
+ wakes = [wake] + args.ewakes
179
+ print("Calculating:", wakes)
180
+
181
+ results = calc(mbook, farm, states, wakes, points, args).reshape(nd, ny)
182
+
183
+ for di, d in enumerate(args.dists_D):
184
+ if nrows == 1 or ncols == 1:
185
+ ax = axs[di]
186
+ else:
187
+ xi = int(di / ncols)
188
+ yi = di % ncols
189
+ ax = axs[xi, yi]
190
+
191
+ if args.deficit:
192
+ dfz = (args.ws - results[di]) / args.ws
193
+ ax.plot(ylist / D, dfz, label=wake)
194
+ ax.set_ylabel("WS deficit")
195
+ else:
196
+ ax.plot(ylist / D, results[di], label=wake)
197
+ ax.set_ylabel(args.var)
198
+
199
+ ax.set_title(f"x = {d} D")
200
+ ax.set_xlabel("y/D")
201
+ ax.grid()
202
+
203
+ ax.legend(loc="best")
204
+ if not args.nofig:
205
+ plt.show()
206
+ plt.close(fig)
207
+
208
+ # x line:
209
+
210
+ print("\nCalculating x line\n")
211
+
212
+ xlist = np.arange(-1, args.dists_D[-1] + args.step, args.step) * D
213
+ nx = len(xlist)
214
+ points = np.zeros((nx, 3))
215
+ points[:, 2] = args.height if args.height is not None else H
216
+ points[:, 0] = xlist
217
+
218
+ figsize = (args.plot_cols * args.figsize_scale, args.figsize_scale)
219
+ fig, ax = plt.subplots(figsize=figsize)
220
+
221
+ for wake in args.wakes:
222
+ wakes = [wake] + args.ewakes
223
+ print("Calculating:", wakes)
224
+
225
+ results = calc(mbook, farm, states, wakes, points, args)
226
+
227
+ if args.deficit:
228
+ dfz = (args.ws - results[0]) / args.ws
229
+ ax.plot(xlist / D, dfz, label=wake)
230
+ ax.set_ylabel("WS deficit")
231
+ else:
232
+ ax.plot(xlist / D, results[0], label=wake)
233
+ ax.set_ylabel(args.var)
234
+
235
+ ax.set_title(f"y = 0")
236
+ ax.set_xlabel("x/D")
237
+ ax.legend(loc="best")
238
+ ax.grid()
239
+
240
+ if not args.nofig:
241
+ plt.show()