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

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

Potentially problematic release.


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

Files changed (174) hide show
  1. docs/source/conf.py +353 -0
  2. examples/abl_states/run.py +160 -0
  3. examples/compare_rotors_pwakes/run.py +217 -0
  4. examples/compare_wakes/run.py +241 -0
  5. examples/dyn_wakes/run.py +311 -0
  6. examples/field_data_nc/run.py +121 -0
  7. examples/induction_RHB/run.py +201 -0
  8. examples/multi_height/run.py +113 -0
  9. examples/power_mask/run.py +249 -0
  10. examples/random_timeseries/run.py +210 -0
  11. examples/scan_row/run.py +193 -0
  12. examples/sector_management/run.py +162 -0
  13. examples/sequential/run.py +209 -0
  14. examples/single_state/run.py +201 -0
  15. examples/states_lookup_table/run.py +137 -0
  16. examples/streamline_wakes/run.py +138 -0
  17. examples/tab_file/run.py +142 -0
  18. examples/timelines/run.py +267 -0
  19. examples/timeseries/run.py +183 -0
  20. examples/timeseries_slurm/run.py +185 -0
  21. examples/wind_rose/run.py +141 -0
  22. examples/windio/run.py +29 -0
  23. examples/yawed_wake/run.py +196 -0
  24. foxes/__init__.py +4 -8
  25. foxes/algorithms/__init__.py +1 -1
  26. foxes/algorithms/downwind/downwind.py +232 -101
  27. foxes/algorithms/downwind/models/farm_wakes_calc.py +11 -6
  28. foxes/algorithms/downwind/models/init_farm_data.py +1 -1
  29. foxes/algorithms/downwind/models/point_wakes_calc.py +5 -6
  30. foxes/algorithms/downwind/models/reorder_farm_output.py +0 -1
  31. foxes/algorithms/downwind/models/set_amb_point_results.py +4 -2
  32. foxes/algorithms/iterative/iterative.py +73 -33
  33. foxes/algorithms/iterative/models/farm_wakes_calc.py +11 -6
  34. foxes/algorithms/sequential/models/plugin.py +1 -1
  35. foxes/algorithms/sequential/sequential.py +126 -255
  36. foxes/constants.py +17 -2
  37. foxes/core/__init__.py +1 -0
  38. foxes/core/algorithm.py +631 -146
  39. foxes/core/data.py +252 -20
  40. foxes/core/data_calc_model.py +13 -289
  41. foxes/core/engine.py +630 -0
  42. foxes/core/farm_controller.py +37 -9
  43. foxes/core/farm_data_model.py +15 -0
  44. foxes/core/model.py +133 -80
  45. foxes/core/point_data_model.py +15 -0
  46. foxes/core/rotor_model.py +27 -21
  47. foxes/core/states.py +16 -0
  48. foxes/core/turbine_type.py +28 -0
  49. foxes/core/wake_frame.py +22 -4
  50. foxes/core/wake_model.py +2 -3
  51. foxes/data/windio/windio_5turbines_timeseries.yaml +23 -1
  52. foxes/engines/__init__.py +16 -0
  53. foxes/engines/dask.py +975 -0
  54. foxes/engines/default.py +75 -0
  55. foxes/engines/futures.py +72 -0
  56. foxes/engines/mpi.py +38 -0
  57. foxes/engines/multiprocess.py +74 -0
  58. foxes/engines/numpy.py +185 -0
  59. foxes/engines/pool.py +263 -0
  60. foxes/engines/single.py +139 -0
  61. foxes/input/farm_layout/__init__.py +1 -0
  62. foxes/input/farm_layout/from_csv.py +4 -0
  63. foxes/input/farm_layout/from_json.py +1 -1
  64. foxes/input/farm_layout/grid.py +2 -2
  65. foxes/input/farm_layout/ring.py +65 -0
  66. foxes/input/farm_layout/row.py +2 -2
  67. foxes/input/states/__init__.py +6 -0
  68. foxes/input/states/create/random_abl_states.py +1 -1
  69. foxes/input/states/field_data_nc.py +157 -32
  70. foxes/input/states/multi_height.py +127 -13
  71. foxes/input/states/one_point_flow.py +577 -0
  72. foxes/input/states/scan_ws.py +73 -2
  73. foxes/input/states/states_table.py +204 -35
  74. foxes/input/windio/__init__.py +1 -1
  75. foxes/input/windio/get_states.py +44 -23
  76. foxes/input/windio/read_attributes.py +41 -16
  77. foxes/input/windio/read_farm.py +116 -102
  78. foxes/input/windio/read_fields.py +13 -6
  79. foxes/input/windio/read_outputs.py +63 -22
  80. foxes/input/windio/runner.py +31 -17
  81. foxes/input/windio/windio.py +36 -22
  82. foxes/models/ground_models/wake_mirror.py +8 -4
  83. foxes/models/model_book.py +29 -18
  84. foxes/models/partial_wakes/rotor_points.py +3 -3
  85. foxes/models/rotor_models/centre.py +4 -0
  86. foxes/models/rotor_models/grid.py +22 -23
  87. foxes/models/rotor_models/levels.py +4 -5
  88. foxes/models/turbine_models/calculator.py +0 -2
  89. foxes/models/turbine_models/lookup_table.py +27 -2
  90. foxes/models/turbine_models/rotor_centre_calc.py +4 -3
  91. foxes/models/turbine_models/set_farm_vars.py +103 -34
  92. foxes/models/turbine_types/PCt_file.py +24 -0
  93. foxes/models/turbine_types/PCt_from_two.py +24 -0
  94. foxes/models/turbine_types/__init__.py +1 -0
  95. foxes/models/turbine_types/lookup.py +316 -0
  96. foxes/models/turbine_types/null_type.py +50 -0
  97. foxes/models/turbine_types/wsrho2PCt_from_two.py +24 -0
  98. foxes/models/turbine_types/wsti2PCt_from_two.py +24 -0
  99. foxes/models/vertical_profiles/data_profile.py +1 -1
  100. foxes/models/wake_frames/__init__.py +1 -0
  101. foxes/models/wake_frames/dynamic_wakes.py +424 -0
  102. foxes/models/wake_frames/farm_order.py +23 -3
  103. foxes/models/wake_frames/rotor_wd.py +4 -2
  104. foxes/models/wake_frames/seq_dynamic_wakes.py +56 -63
  105. foxes/models/wake_frames/streamlines.py +19 -20
  106. foxes/models/wake_frames/timelines.py +328 -127
  107. foxes/models/wake_frames/yawed_wakes.py +4 -1
  108. foxes/models/wake_models/dist_sliced.py +1 -3
  109. foxes/models/wake_models/induction/rankine_half_body.py +4 -4
  110. foxes/models/wake_models/induction/rathmann.py +2 -2
  111. foxes/models/wake_models/induction/self_similar.py +2 -2
  112. foxes/models/wake_models/induction/vortex_sheet.py +2 -2
  113. foxes/models/wake_models/ti/iec_ti.py +34 -17
  114. foxes/models/wake_models/top_hat.py +1 -1
  115. foxes/models/wake_models/wind/bastankhah14.py +2 -2
  116. foxes/models/wake_models/wind/bastankhah16.py +8 -7
  117. foxes/models/wake_models/wind/jensen.py +1 -1
  118. foxes/models/wake_models/wind/turbopark.py +2 -2
  119. foxes/output/__init__.py +4 -1
  120. foxes/output/farm_layout.py +2 -2
  121. foxes/output/flow_plots_2d/__init__.py +0 -1
  122. foxes/output/flow_plots_2d/flow_plots.py +70 -30
  123. foxes/output/grids.py +91 -21
  124. foxes/output/seq_plugins/__init__.py +2 -0
  125. foxes/output/{flow_plots_2d → seq_plugins}/seq_flow_ani_plugin.py +62 -20
  126. foxes/output/seq_plugins/seq_wake_debug_plugin.py +145 -0
  127. foxes/output/slice_data.py +131 -111
  128. foxes/output/state_turbine_map.py +18 -13
  129. foxes/output/state_turbine_table.py +19 -19
  130. foxes/utils/__init__.py +1 -1
  131. foxes/utils/dev_utils.py +42 -0
  132. foxes/utils/dict.py +1 -1
  133. foxes/utils/factory.py +147 -52
  134. foxes/utils/pandas_helpers.py +4 -3
  135. foxes/utils/wind_dir.py +0 -2
  136. foxes/utils/xarray_utils.py +23 -13
  137. foxes/variables.py +37 -0
  138. {foxes-0.8.2.dist-info → foxes-1.0.dist-info}/METADATA +71 -33
  139. foxes-1.0.dist-info/RECORD +307 -0
  140. {foxes-0.8.2.dist-info → foxes-1.0.dist-info}/WHEEL +1 -1
  141. foxes-1.0.dist-info/top_level.txt +4 -0
  142. tests/0_consistency/iterative/test_iterative.py +92 -0
  143. tests/0_consistency/partial_wakes/test_partial_wakes.py +90 -0
  144. tests/1_verification/flappy_0_6/PCt_files/flappy/run.py +85 -0
  145. tests/1_verification/flappy_0_6/PCt_files/test_PCt_files.py +103 -0
  146. tests/1_verification/flappy_0_6/abl_states/flappy/run.py +85 -0
  147. tests/1_verification/flappy_0_6/abl_states/test_abl_states.py +87 -0
  148. tests/1_verification/flappy_0_6/partial_top_hat/flappy/run.py +82 -0
  149. tests/1_verification/flappy_0_6/partial_top_hat/test_partial_top_hat.py +82 -0
  150. tests/1_verification/flappy_0_6/row_Jensen_linear_centre/flappy/run.py +92 -0
  151. tests/1_verification/flappy_0_6/row_Jensen_linear_centre/test_row_Jensen_linear_centre.py +93 -0
  152. tests/1_verification/flappy_0_6/row_Jensen_linear_tophat/flappy/run.py +92 -0
  153. tests/1_verification/flappy_0_6/row_Jensen_linear_tophat/test_row_Jensen_linear_tophat.py +96 -0
  154. tests/1_verification/flappy_0_6/row_Jensen_linear_tophat_IECTI2005/flappy/run.py +94 -0
  155. tests/1_verification/flappy_0_6/row_Jensen_linear_tophat_IECTI2005/test_row_Jensen_linear_tophat_IECTI_2005.py +122 -0
  156. tests/1_verification/flappy_0_6/row_Jensen_linear_tophat_IECTI2019/flappy/run.py +94 -0
  157. tests/1_verification/flappy_0_6/row_Jensen_linear_tophat_IECTI2019/test_row_Jensen_linear_tophat_IECTI_2019.py +122 -0
  158. tests/1_verification/flappy_0_6/row_Jensen_quadratic_centre/flappy/run.py +92 -0
  159. tests/1_verification/flappy_0_6/row_Jensen_quadratic_centre/test_row_Jensen_quadratic_centre.py +93 -0
  160. tests/1_verification/flappy_0_6_2/grid_rotors/flappy/run.py +85 -0
  161. tests/1_verification/flappy_0_6_2/grid_rotors/test_grid_rotors.py +130 -0
  162. tests/1_verification/flappy_0_6_2/row_Bastankhah_Crespo/flappy/run.py +96 -0
  163. tests/1_verification/flappy_0_6_2/row_Bastankhah_Crespo/test_row_Bastankhah_Crespo.py +116 -0
  164. tests/1_verification/flappy_0_6_2/row_Bastankhah_linear_centre/flappy/run.py +93 -0
  165. tests/1_verification/flappy_0_6_2/row_Bastankhah_linear_centre/test_row_Bastankhah_linear_centre.py +99 -0
  166. tests/3_examples/test_examples.py +34 -0
  167. foxes/VERSION +0 -1
  168. foxes/output/flow_plots_2d.py +0 -0
  169. foxes/utils/runners/__init__.py +0 -1
  170. foxes/utils/runners/runners.py +0 -280
  171. foxes-0.8.2.dist-info/RECORD +0 -247
  172. foxes-0.8.2.dist-info/top_level.txt +0 -1
  173. foxes-0.8.2.dist-info/zip-safe +0 -1
  174. {foxes-0.8.2.dist-info → foxes-1.0.dist-info}/LICENSE +0 -0
@@ -0,0 +1,267 @@
1
+ import time
2
+ import argparse
3
+ import numpy as np
4
+ import matplotlib.pyplot as plt
5
+ from pathlib import Path
6
+
7
+ import foxes
8
+ import foxes.variables as FV
9
+
10
+
11
+ if __name__ == "__main__":
12
+ parser = argparse.ArgumentParser()
13
+ parser.add_argument(
14
+ "-a", "--animation", help="Write flow animation file", action="store_true"
15
+ )
16
+ parser.add_argument(
17
+ "-A",
18
+ "--ani_file",
19
+ help="Path to the animation file to be written",
20
+ default="ani.gif",
21
+ )
22
+ parser.add_argument(
23
+ "-F",
24
+ "--fps",
25
+ help="The frames per second value for the animation",
26
+ type=int,
27
+ default=4,
28
+ )
29
+ parser.add_argument(
30
+ "-b",
31
+ "--background",
32
+ help="Switch on dynamic background interpretation",
33
+ action="store_true",
34
+ )
35
+ parser.add_argument(
36
+ "-S",
37
+ "--max_state",
38
+ help="States subset to the first n states",
39
+ type=int,
40
+ default=None,
41
+ )
42
+ parser.add_argument(
43
+ "-R",
44
+ "--ref_xy",
45
+ help="The reference point x y",
46
+ type=float,
47
+ default=[2500, 2500],
48
+ nargs="+",
49
+ )
50
+ parser.add_argument(
51
+ "-nt", "--n_turbines", help="The number of turbines", default=9, type=int
52
+ )
53
+ parser.add_argument(
54
+ "-s",
55
+ "--states",
56
+ help="The timeseries input file (path or static)",
57
+ default="timeseries_100.csv.gz",
58
+ )
59
+ parser.add_argument(
60
+ "-t",
61
+ "--turbine_file",
62
+ help="The P-ct-curve csv file (path or static)",
63
+ default="NREL-5MW-D126-H90.csv",
64
+ )
65
+ parser.add_argument("-r", "--rotor", help="The rotor model", default="centre")
66
+ parser.add_argument(
67
+ "-p", "--pwakes", help="The partial wakes models", default=None, nargs="+"
68
+ )
69
+ parser.add_argument("-sc", "--scheduler", help="The scheduler choice", default=None)
70
+ parser.add_argument(
71
+ "-w",
72
+ "--wakes",
73
+ help="The wake models",
74
+ default=["Bastankhah2014_linear_lim_k004"],
75
+ nargs="+",
76
+ )
77
+ parser.add_argument("-f", "--frame", help="The wake frame", default="timelines")
78
+ parser.add_argument(
79
+ "-m", "--tmodels", help="The turbine models", default=[], nargs="+"
80
+ )
81
+ parser.add_argument(
82
+ "-sl",
83
+ "--show_layout",
84
+ help="Flag for showing layout figure",
85
+ action="store_true",
86
+ )
87
+ parser.add_argument("-e", "--engine", help="The engine", default="process")
88
+ parser.add_argument(
89
+ "-n", "--n_cpus", help="The number of cpus", default=None, type=int
90
+ )
91
+ parser.add_argument(
92
+ "-c",
93
+ "--chunksize_states",
94
+ help="The chunk size for states",
95
+ default=None,
96
+ type=int,
97
+ )
98
+ parser.add_argument(
99
+ "-C",
100
+ "--chunksize_points",
101
+ help="The chunk size for points",
102
+ default=5000,
103
+ type=int,
104
+ )
105
+ parser.add_argument(
106
+ "-nf", "--nofig", help="Do not show figures", action="store_true"
107
+ )
108
+ args = parser.parse_args()
109
+
110
+ mbook = foxes.models.ModelBook()
111
+ ttype = foxes.models.turbine_types.PCtFile(args.turbine_file)
112
+ mbook.turbine_types[ttype.name] = ttype
113
+
114
+ if not args.background:
115
+ States = foxes.input.states.Timeseries
116
+ kwargs = {}
117
+ else:
118
+ States = foxes.input.states.OnePointFlowTimeseries
119
+ kwargs = {"ref_xy": args.ref_xy}
120
+
121
+ states = States(
122
+ data_source=args.states,
123
+ output_vars=[FV.WS, FV.WD, FV.TI, FV.RHO],
124
+ var2col={FV.WS: "ws", FV.WD: "wd", FV.TI: "ti"},
125
+ fixed_vars={FV.RHO: 1.225, FV.TI: 0.07},
126
+ states_sel=range(args.max_state) if args.max_state is not None else None,
127
+ **kwargs,
128
+ )
129
+
130
+ farm = foxes.WindFarm()
131
+ N = int(args.n_turbines**0.5)
132
+ foxes.input.farm_layout.add_grid(
133
+ farm,
134
+ xy_base=np.array([0.0, 0.0]),
135
+ step_vectors=np.array([[1000.0, 0], [0, 800.0]]),
136
+ steps=(N, N),
137
+ turbine_models=args.tmodels + [ttype.name],
138
+ )
139
+
140
+ if not args.nofig and args.show_layout:
141
+ ax = foxes.output.FarmLayoutOutput(farm).get_figure()
142
+ plt.show()
143
+ plt.close(ax.get_figure())
144
+
145
+ algo = foxes.algorithms.Iterative(
146
+ farm,
147
+ states=states,
148
+ rotor_model=args.rotor,
149
+ wake_models=args.wakes,
150
+ wake_frame=args.frame,
151
+ partial_wakes=args.pwakes,
152
+ mbook=mbook,
153
+ engine=args.engine,
154
+ n_procs=args.n_cpus,
155
+ chunk_size_states=args.chunksize_states,
156
+ chunk_size_points=args.chunksize_points,
157
+ verbosity=1,
158
+ )
159
+
160
+ time0 = time.time()
161
+ farm_results = algo.calc_farm()
162
+ time1 = time.time()
163
+
164
+ print("\nCalc time =", time1 - time0, "\n")
165
+
166
+ o = foxes.output.FarmResultsEval(farm_results)
167
+ o.add_capacity(algo)
168
+ o.add_capacity(algo, ambient=True)
169
+ o.add_efficiency()
170
+
171
+ print("\nFarm results:\n")
172
+ print(farm_results)
173
+
174
+ # state-turbine results
175
+ farm_df = farm_results.to_dataframe()
176
+ print("\nFarm results data:\n")
177
+ print(
178
+ farm_df[
179
+ [
180
+ FV.X,
181
+ FV.Y,
182
+ FV.WD,
183
+ FV.AMB_REWS,
184
+ FV.REWS,
185
+ FV.AMB_TI,
186
+ FV.TI,
187
+ FV.AMB_P,
188
+ FV.P,
189
+ FV.EFF,
190
+ ]
191
+ ]
192
+ )
193
+ print()
194
+ print(farm_df[[FV.AMB_REWS, FV.REWS, FV.CT, FV.EFF]].describe())
195
+
196
+ # power results
197
+ P0 = o.calc_mean_farm_power(ambient=True)
198
+ P = o.calc_mean_farm_power()
199
+ print(f"\nFarm power : {P/1000:.1f} MW")
200
+ print(f"Farm ambient power: {P0/1000:.1f} MW")
201
+ print(f"Farm efficiency : {o.calc_farm_efficiency()*100:.2f} %")
202
+
203
+ if not args.nofig:
204
+ sts = np.arange(farm_results.sizes["state"])
205
+ plt.plot(sts, farm_results.REWS[:, 4], label="Turbine 4")
206
+ plt.plot(sts, farm_results.REWS[:, 7], label="Turbine 7")
207
+ plt.legend()
208
+ plt.xlabel("State")
209
+ plt.ylabel("REWS [m/s]")
210
+ plt.show()
211
+
212
+ if not args.nofig and args.animation:
213
+ print("\nCalculating animation")
214
+
215
+ fig, axs = plt.subplots(
216
+ 2, 1, figsize=(5.2, 7), gridspec_kw={"height_ratios": [3, 1]}
217
+ )
218
+
219
+ anim = foxes.output.Animator(fig)
220
+ of = foxes.output.FlowPlots2D(algo, farm_results)
221
+ anim.add_generator(
222
+ of.gen_states_fig_xy(
223
+ FV.WS,
224
+ resolution=30,
225
+ quiver_pars=dict(angles="xy", scale_units="xy", scale=0.013),
226
+ quiver_n=35,
227
+ xmax=5000,
228
+ ymax=5000,
229
+ vmin=0,
230
+ fig=fig,
231
+ ax=axs[0],
232
+ ret_im=True,
233
+ title=None,
234
+ animated=True,
235
+ )
236
+ )
237
+ anim.add_generator(
238
+ o.gen_stdata(
239
+ turbines=[4, 7],
240
+ variable=FV.REWS,
241
+ fig=fig,
242
+ ax=axs[1],
243
+ ret_im=True,
244
+ legloc="upper left",
245
+ animated=True,
246
+ )
247
+ )
248
+
249
+ ani = anim.animate()
250
+
251
+ lo = foxes.output.FarmLayoutOutput(farm)
252
+ lo.get_figure(
253
+ fig=fig,
254
+ ax=axs[0],
255
+ title="",
256
+ annotate=1,
257
+ anno_delx=-120,
258
+ anno_dely=-60,
259
+ alpha=0,
260
+ )
261
+
262
+ fpath = Path(args.ani_file)
263
+ print("Writing file", fpath)
264
+ if fpath.suffix == ".gif":
265
+ ani.save(filename=fpath, writer="pillow", fps=args.fps)
266
+ else:
267
+ ani.save(filename=fpath, writer="ffmpeg", fps=args.fps)
@@ -0,0 +1,183 @@
1
+ import time
2
+ import argparse
3
+ import matplotlib.pyplot as plt
4
+
5
+ import foxes
6
+ import foxes.variables as FV
7
+
8
+ if __name__ == "__main__":
9
+ parser = argparse.ArgumentParser()
10
+ parser.add_argument(
11
+ "-l",
12
+ "--layout",
13
+ help="The wind farm layout file (path or static)",
14
+ default="test_farm_67.csv",
15
+ )
16
+ parser.add_argument(
17
+ "-s",
18
+ "--states",
19
+ help="The timeseries input file (path or static)",
20
+ default="timeseries_8000.csv.gz",
21
+ )
22
+ parser.add_argument(
23
+ "-t",
24
+ "--turbine_file",
25
+ help="The P-ct-curve csv file (path or static)",
26
+ default="NREL-5MW-D126-H90.csv",
27
+ )
28
+ parser.add_argument("-r", "--rotor", help="The rotor model", default="centre")
29
+ parser.add_argument(
30
+ "-p", "--pwakes", help="The partial wakes models", default="centre", nargs="+"
31
+ )
32
+ parser.add_argument(
33
+ "-w",
34
+ "--wakes",
35
+ help="The wake models",
36
+ default=["Jensen_linear_k007"],
37
+ nargs="+",
38
+ )
39
+ parser.add_argument("-f", "--frame", help="The wake frame", default="rotor_wd")
40
+ parser.add_argument(
41
+ "-m", "--tmodels", help="The turbine models", default=[], nargs="+"
42
+ )
43
+ parser.add_argument(
44
+ "-sl",
45
+ "--show_layout",
46
+ help="Flag for showing layout figure",
47
+ action="store_true",
48
+ )
49
+ parser.add_argument("-e", "--engine", help="The engine", default="process")
50
+ parser.add_argument(
51
+ "-n", "--n_cpus", help="The number of cpus", default=None, type=int
52
+ )
53
+ parser.add_argument(
54
+ "-c",
55
+ "--chunksize_states",
56
+ help="The chunk size for states",
57
+ default=None,
58
+ type=int,
59
+ )
60
+ parser.add_argument(
61
+ "-C",
62
+ "--chunksize_points",
63
+ help="The chunk size for points",
64
+ default=5000,
65
+ type=int,
66
+ )
67
+ parser.add_argument(
68
+ "-ts",
69
+ "--timestep",
70
+ help="The timestep of the input timeseries or data in minutes",
71
+ default=60 * 24 * 365, # default is one year
72
+ )
73
+ parser.add_argument(
74
+ "-it", "--iterative", help="Use iterative algorithm", action="store_true"
75
+ )
76
+ parser.add_argument(
77
+ "-nf", "--nofig", help="Do not show figures", action="store_true"
78
+ )
79
+ args = parser.parse_args()
80
+
81
+ mbook = foxes.models.ModelBook()
82
+ ttype = foxes.models.turbine_types.PCtFile(args.turbine_file)
83
+ mbook.turbine_types[ttype.name] = ttype
84
+
85
+ states = foxes.input.states.Timeseries(
86
+ data_source=args.states,
87
+ output_vars=[FV.WS, FV.WD, FV.TI, FV.RHO],
88
+ var2col={FV.WS: "ws", FV.WD: "wd", FV.TI: "ti"},
89
+ fixed_vars={FV.RHO: 1.225},
90
+ )
91
+
92
+ farm = foxes.WindFarm()
93
+ foxes.input.farm_layout.add_from_file(
94
+ farm, args.layout, turbine_models=args.tmodels + [ttype.name]
95
+ )
96
+
97
+ if args.show_layout:
98
+ ax = foxes.output.FarmLayoutOutput(farm).get_figure()
99
+ plt.show()
100
+ plt.close(ax.get_figure())
101
+
102
+ Algo = foxes.algorithms.Iterative if args.iterative else foxes.algorithms.Downwind
103
+ algo = Algo(
104
+ farm,
105
+ states=states,
106
+ rotor_model=args.rotor,
107
+ wake_models=args.wakes,
108
+ wake_frame=args.frame,
109
+ partial_wakes=args.pwakes,
110
+ mbook=mbook,
111
+ engine=args.engine,
112
+ n_procs=args.n_cpus,
113
+ chunk_size_states=args.chunksize_states,
114
+ chunk_size_points=args.chunksize_points,
115
+ verbosity=1,
116
+ )
117
+
118
+ time0 = time.time()
119
+ farm_results = algo.calc_farm()
120
+ time1 = time.time()
121
+
122
+ print("\nFarm results:\n")
123
+ print(farm_results)
124
+
125
+ print("\nCalc time =", time1 - time0, "\n")
126
+
127
+ o = foxes.output.FarmResultsEval(farm_results)
128
+ o.add_capacity(algo)
129
+ o.add_capacity(algo, ambient=True)
130
+ o.add_efficiency()
131
+
132
+ print("\nFarm results:\n")
133
+ print(farm_results)
134
+
135
+ # state-turbine results
136
+ farm_df = farm_results.to_dataframe()
137
+ print("\nFarm results data:\n")
138
+ print(
139
+ farm_df[
140
+ [
141
+ FV.X,
142
+ FV.WD,
143
+ FV.AMB_REWS,
144
+ FV.REWS,
145
+ FV.AMB_TI,
146
+ FV.TI,
147
+ FV.AMB_P,
148
+ FV.P,
149
+ FV.EFF,
150
+ ]
151
+ ]
152
+ )
153
+ print()
154
+
155
+ # results by turbine
156
+ turbine_results = o.reduce_states(
157
+ {
158
+ FV.AMB_P: "mean",
159
+ FV.P: "mean",
160
+ FV.AMB_CAP: "mean",
161
+ FV.CAP: "mean",
162
+ FV.EFF: "mean",
163
+ }
164
+ )
165
+ turbine_results[FV.AMB_YLD] = o.calc_turbine_yield(
166
+ algo=algo, annual=True, ambient=True
167
+ )
168
+ turbine_results[FV.YLD] = o.calc_turbine_yield(algo=algo, annual=True)
169
+ print("\nResults by turbine:\n")
170
+ print(turbine_results)
171
+
172
+ # power results
173
+ P0 = o.calc_mean_farm_power(ambient=True)
174
+ P = o.calc_mean_farm_power()
175
+ print(f"\nFarm power : {P/1000:.1f} MW")
176
+ print(f"Farm ambient power: {P0/1000:.1f} MW")
177
+ print(f"Farm efficiency : {o.calc_farm_efficiency()*100:.2f} %")
178
+ print(f"Annual farm yield : {turbine_results[FV.YLD].sum():.2f} GWh")
179
+
180
+ if not args.nofig:
181
+ o = foxes.output.StateTurbineMap(farm_results)
182
+ ax = o.plot_map(FV.P, cmap="inferno", figsize=(6, 7))
183
+ plt.show()
@@ -0,0 +1,185 @@
1
+ import time
2
+ import argparse
3
+ import matplotlib.pyplot as plt
4
+
5
+ import foxes
6
+ import foxes.variables as FV
7
+
8
+ if __name__ == "__main__":
9
+ parser = argparse.ArgumentParser()
10
+ parser.add_argument(
11
+ "-l",
12
+ "--layout",
13
+ help="The wind farm layout file (path or static)",
14
+ default="test_farm_67.csv",
15
+ )
16
+ parser.add_argument(
17
+ "-s",
18
+ "--states",
19
+ help="The timeseries input file (path or static)",
20
+ default="timeseries_8000.csv.gz",
21
+ )
22
+ parser.add_argument(
23
+ "-t",
24
+ "--turbine_file",
25
+ help="The P-ct-curve csv file (path or static)",
26
+ default="NREL-5MW-D126-H90.csv",
27
+ )
28
+ parser.add_argument("-r", "--rotor", help="The rotor model", default="centre")
29
+ parser.add_argument(
30
+ "-p", "--pwakes", help="The partial wakes models", default=None, nargs="+"
31
+ )
32
+ parser.add_argument(
33
+ "-w",
34
+ "--wakes",
35
+ help="The wake models",
36
+ default=["Jensen_linear_k007"],
37
+ nargs="+",
38
+ )
39
+ parser.add_argument("-f", "--frame", help="The wake frame", default="rotor_wd")
40
+ parser.add_argument(
41
+ "-m", "--tmodels", help="The turbine models", default=[], nargs="+"
42
+ )
43
+ parser.add_argument(
44
+ "-sl",
45
+ "--show_layout",
46
+ help="Flag for showing layout figure",
47
+ action="store_true",
48
+ )
49
+ parser.add_argument(
50
+ "-ts",
51
+ "--timestep",
52
+ help="The timestep of the input timeseries or data in minutes",
53
+ default=60 * 24 * 365, # default is one year
54
+ )
55
+ parser.add_argument(
56
+ "-it", "--iterative", help="Use iterative algorithm", action="store_true"
57
+ )
58
+ parser.add_argument(
59
+ "-n", "--n_cpus", help="The number of cpus", default=None, type=int
60
+ )
61
+ parser.add_argument(
62
+ "-c",
63
+ "--chunksize_states",
64
+ help="The chunk size for states",
65
+ default=None,
66
+ type=int,
67
+ )
68
+ parser.add_argument(
69
+ "-C",
70
+ "--chunksize_points",
71
+ help="The chunk size for points",
72
+ default=5000,
73
+ type=int,
74
+ )
75
+ parser.add_argument(
76
+ "-nf", "--nofig", help="Do not show figures", action="store_true"
77
+ )
78
+ args = parser.parse_args()
79
+
80
+ mbook = foxes.models.ModelBook()
81
+ ttype = foxes.models.turbine_types.PCtFile(args.turbine_file)
82
+ mbook.turbine_types[ttype.name] = ttype
83
+
84
+ states = foxes.input.states.Timeseries(
85
+ data_source=args.states,
86
+ output_vars=[FV.WS, FV.WD, FV.TI, FV.RHO],
87
+ var2col={FV.WS: "ws", FV.WD: "wd", FV.TI: "ti"},
88
+ fixed_vars={FV.RHO: 1.225},
89
+ )
90
+
91
+ farm = foxes.WindFarm()
92
+ foxes.input.farm_layout.add_from_file(
93
+ farm, args.layout, turbine_models=args.tmodels + [ttype.name]
94
+ )
95
+
96
+ if not args.nofig and args.show_layout:
97
+ ax = foxes.output.FarmLayoutOutput(farm).get_figure()
98
+ plt.show()
99
+ plt.close(ax.get_figure())
100
+
101
+ Algo = foxes.algorithms.Iterative if args.iterative else foxes.algorithms.Downwind
102
+ algo = Algo(
103
+ farm,
104
+ states=states,
105
+ rotor_model=args.rotor,
106
+ wake_models=args.wakes,
107
+ wake_frame=args.frame,
108
+ partial_wakes=args.pwakes,
109
+ mbook=mbook,
110
+ )
111
+
112
+ cluster_pars = {
113
+ "nodes": 1, # number of nodes
114
+ "cores": 24, # number of cores per node
115
+ "processes": 4, # number of workers per node
116
+ "memory": "64GB", # memory per node
117
+ "walltime": "00:00:10",
118
+ "queue": "cfds.p",
119
+ # "silence_logs": "info", # print all info log
120
+ }
121
+
122
+ with foxes.Engine.new(
123
+ engine_type="slurm_cluster",
124
+ n_procs=4,
125
+ cluster_pars=cluster_pars,
126
+ chunk_size_states=args.chunksize_states,
127
+ chunk_size_points=args.chunksize_points,
128
+ ):
129
+ time0 = time.time()
130
+ farm_results = algo.calc_farm()
131
+ time1 = time.time()
132
+
133
+ print("\nCalc time =", time1 - time0, "\n")
134
+
135
+ o = foxes.output.FarmResultsEval(farm_results)
136
+ o.add_capacity(algo)
137
+ o.add_capacity(algo, ambient=True)
138
+ o.add_efficiency()
139
+
140
+ print("\nFarm results:\n")
141
+ print(farm_results)
142
+
143
+ # state-turbine results
144
+ farm_df = farm_results.to_dataframe()
145
+ print("\nFarm results data:\n")
146
+ print(
147
+ farm_df[
148
+ [
149
+ FV.X,
150
+ FV.WD,
151
+ FV.AMB_REWS,
152
+ FV.REWS,
153
+ FV.AMB_TI,
154
+ FV.TI,
155
+ FV.AMB_P,
156
+ FV.P,
157
+ FV.EFF,
158
+ ]
159
+ ]
160
+ )
161
+
162
+ # results by turbine
163
+ turbine_results = o.reduce_states(
164
+ {
165
+ FV.AMB_P: "mean",
166
+ FV.P: "mean",
167
+ FV.AMB_CAP: "mean",
168
+ FV.CAP: "mean",
169
+ FV.EFF: "mean",
170
+ }
171
+ )
172
+ turbine_results[FV.AMB_YLD] = o.calc_turbine_yield(
173
+ algo=algo, annual=True, ambient=True
174
+ )
175
+ turbine_results[FV.YLD] = o.calc_turbine_yield(algo=algo, annual=True)
176
+ print("\nResults by turbine:\n")
177
+ print(turbine_results)
178
+
179
+ # power results
180
+ P0 = o.calc_mean_farm_power(ambient=True)
181
+ P = o.calc_mean_farm_power()
182
+ print(f"\nFarm power : {P/1000:.1f} MW")
183
+ print(f"Farm ambient power: {P0/1000:.1f} MW")
184
+ print(f"Farm efficiency : {o.calc_farm_efficiency()*100:.2f} %")
185
+ print(f"Annual farm yield : {turbine_results[FV.YLD].sum():.2f} GWh")