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,311 @@
1
+ import time
2
+ import argparse
3
+ import numpy as np
4
+ import pandas as pd
5
+ import matplotlib.pyplot as plt
6
+ from pathlib import Path
7
+
8
+ import foxes
9
+ import foxes.variables as FV
10
+
11
+
12
+ if __name__ == "__main__":
13
+ parser = argparse.ArgumentParser()
14
+ parser.add_argument(
15
+ "-a", "--animation", help="Write flow animation file", action="store_true"
16
+ )
17
+ parser.add_argument(
18
+ "-A",
19
+ "--ani_file",
20
+ help="Path to the animation file to be written",
21
+ default="ani.gif",
22
+ )
23
+ parser.add_argument(
24
+ "-F",
25
+ "--fps",
26
+ help="The frames per second value for the animation",
27
+ type=int,
28
+ default=4,
29
+ )
30
+ parser.add_argument(
31
+ "-b0",
32
+ "--background0",
33
+ help="Switch off dynamic background interpretation",
34
+ action="store_true",
35
+ )
36
+ parser.add_argument(
37
+ "-ws0", "--fix_ws", help="Switch off dynamic wind speed", action="store_true"
38
+ )
39
+ parser.add_argument(
40
+ "-S",
41
+ "--max_state",
42
+ help="States subset to the first n states",
43
+ type=int,
44
+ default=None,
45
+ )
46
+ parser.add_argument(
47
+ "-R",
48
+ "--ref_xy",
49
+ help="The reference point x y",
50
+ type=float,
51
+ default=[2500, 2500],
52
+ nargs="+",
53
+ )
54
+ parser.add_argument(
55
+ "-nt", "--n_turbines", help="The number of turbines", default=9, type=int
56
+ )
57
+ parser.add_argument(
58
+ "-mit", "--max_it", help="Run until maximal iteration", default=None, type=int
59
+ )
60
+ parser.add_argument(
61
+ "-s",
62
+ "--states",
63
+ help="The timeseries input file (path or static)",
64
+ default="timeseries_100.csv.gz",
65
+ )
66
+ parser.add_argument(
67
+ "-t",
68
+ "--turbine_file",
69
+ help="The P-ct-curve csv file (path or static)",
70
+ default="NREL-5MW-D126-H90.csv",
71
+ )
72
+ parser.add_argument("-r", "--rotor", help="The rotor model", default="centre")
73
+ parser.add_argument(
74
+ "-p", "--pwakes", help="The partial wakes models", default=None, nargs="+"
75
+ )
76
+ parser.add_argument("-sc", "--scheduler", help="The scheduler choice", default=None)
77
+ parser.add_argument(
78
+ "-w",
79
+ "--wakes",
80
+ help="The wake models",
81
+ default=["Bastankhah2014_linear_loc_k004"],
82
+ nargs="+",
83
+ )
84
+ parser.add_argument("-f", "--frame", help="The wake frame", default="dyn_wakes")
85
+ parser.add_argument(
86
+ "-m", "--tmodels", help="The turbine models", default=[], nargs="+"
87
+ )
88
+ parser.add_argument(
89
+ "-sl",
90
+ "--show_layout",
91
+ help="Flag for showing layout figure",
92
+ action="store_true",
93
+ )
94
+ parser.add_argument("-e", "--engine", help="The engine", default="process")
95
+ parser.add_argument(
96
+ "-n", "--n_cpus", help="The number of cpus", default=None, type=int
97
+ )
98
+ parser.add_argument(
99
+ "-c",
100
+ "--chunksize_states",
101
+ help="The chunk size for states",
102
+ default=None,
103
+ type=int,
104
+ )
105
+ parser.add_argument(
106
+ "-C",
107
+ "--chunksize_points",
108
+ help="The chunk size for points",
109
+ default=5000,
110
+ type=int,
111
+ )
112
+ parser.add_argument(
113
+ "-nf", "--nofig", help="Do not show figures", action="store_true"
114
+ )
115
+ args = parser.parse_args()
116
+
117
+ mbook = foxes.models.ModelBook()
118
+ ttype = foxes.models.turbine_types.PCtFile(args.turbine_file)
119
+ mbook.turbine_types[ttype.name] = ttype
120
+ mbook.wake_frames["dyn_wakes"] = foxes.models.wake_frames.DynamicWakes(
121
+ max_length_km=8
122
+ )
123
+
124
+ if args.background0:
125
+ States = foxes.input.states.Timeseries
126
+ kwargs = {}
127
+ else:
128
+ States = foxes.input.states.OnePointFlowTimeseries
129
+ kwargs = {"ref_xy": args.ref_xy}
130
+
131
+ sdata = pd.read_csv(
132
+ foxes.StaticData().get_file_path(foxes.STATES, args.states),
133
+ index_col=0,
134
+ parse_dates=[0],
135
+ )
136
+ if not args.fix_ws:
137
+ n_times = len(sdata.index)
138
+ sdata["ws"] = 5 + 0.3 * np.sin(np.arange(n_times) * 2 * np.pi / 20)
139
+
140
+ states = States(
141
+ data_source=sdata,
142
+ output_vars=[FV.WS, FV.WD, FV.TI, FV.RHO],
143
+ var2col={FV.WS: "ws", FV.WD: "wd", FV.TI: "ti"},
144
+ fixed_vars={FV.RHO: 1.225, FV.TI: 0.07},
145
+ states_sel=range(args.max_state) if args.max_state is not None else None,
146
+ **kwargs,
147
+ )
148
+
149
+ farm = foxes.WindFarm()
150
+ N = int(args.n_turbines**0.5)
151
+ foxes.input.farm_layout.add_grid(
152
+ farm,
153
+ xy_base=np.array([0.0, 0.0]),
154
+ step_vectors=np.array([[1000.0, 0], [0, 800.0]]),
155
+ steps=(N, N),
156
+ turbine_models=args.tmodels + [ttype.name],
157
+ )
158
+
159
+ if not args.nofig and args.show_layout:
160
+ ax = foxes.output.FarmLayoutOutput(farm).get_figure()
161
+ plt.show()
162
+ plt.close(ax.get_figure())
163
+
164
+ engine = foxes.Engine.new(
165
+ engine_type=args.engine,
166
+ n_procs=args.n_cpus,
167
+ chunk_size_states=args.chunksize_states,
168
+ chunk_size_points=args.chunksize_points,
169
+ )
170
+ engine.initialize()
171
+
172
+ algo = foxes.algorithms.Iterative(
173
+ farm,
174
+ states=states,
175
+ rotor_model=args.rotor,
176
+ wake_models=args.wakes,
177
+ wake_frame=args.frame,
178
+ partial_wakes=args.pwakes,
179
+ mbook=mbook,
180
+ max_it=args.max_it,
181
+ conv_crit="default" if args.max_it is None else None,
182
+ verbosity=1,
183
+ )
184
+
185
+ time0 = time.time()
186
+ farm_results = algo.calc_farm()
187
+ time1 = time.time()
188
+
189
+ print("\nCalc time =", time1 - time0, "\n")
190
+
191
+ o = foxes.output.FarmResultsEval(farm_results)
192
+ o.add_capacity(algo)
193
+ o.add_capacity(algo, ambient=True)
194
+ o.add_efficiency()
195
+
196
+ print("\nFarm results:\n")
197
+ print(farm_results)
198
+
199
+ # state-turbine results
200
+ farm_df = farm_results.to_dataframe()
201
+ print("\nFarm results data:\n")
202
+ print(
203
+ farm_df[
204
+ [
205
+ FV.X,
206
+ FV.Y,
207
+ FV.WD,
208
+ FV.AMB_REWS,
209
+ FV.REWS,
210
+ FV.AMB_TI,
211
+ FV.TI,
212
+ FV.AMB_P,
213
+ FV.P,
214
+ FV.EFF,
215
+ ]
216
+ ]
217
+ )
218
+ print()
219
+ print(farm_df[[FV.AMB_REWS, FV.REWS, FV.CT, FV.EFF]].describe())
220
+
221
+ # power results
222
+ P0 = o.calc_mean_farm_power(ambient=True)
223
+ P = o.calc_mean_farm_power()
224
+ print(f"\nFarm power : {P/1000:.1f} MW")
225
+ print(f"Farm ambient power: {P0/1000:.1f} MW")
226
+ print(f"Farm efficiency : {o.calc_farm_efficiency()*100:.2f} %")
227
+
228
+ engine.finalize()
229
+
230
+ if not args.nofig:
231
+ sts = np.arange(farm_results.sizes["state"])
232
+ plt.plot(sts, farm_results.REWS[:, 1], label="Turbine 1")
233
+ plt.plot(sts, farm_results.REWS[:, 4], label="Turbine 4")
234
+ plt.plot(sts, farm_results.REWS[:, 7], label="Turbine 7")
235
+ plt.legend()
236
+ plt.xlabel("State")
237
+ plt.ylabel("REWS [m/s]")
238
+ plt.show()
239
+ plt.close()
240
+
241
+ if not args.nofig and args.animation:
242
+ print("\nCalculating animation")
243
+
244
+ fig, axs = plt.subplots(
245
+ 2, 1, figsize=(5.2, 7), gridspec_kw={"height_ratios": [3, 1]}
246
+ )
247
+
248
+ engine.initialize()
249
+
250
+ of = foxes.output.FlowPlots2D(algo, farm_results)
251
+ ofg = of.gen_states_fig_xy(
252
+ FV.WS,
253
+ resolution=30,
254
+ quiver_pars=dict(angles="xy", scale_units="xy", scale=0.013),
255
+ quiver_n=35,
256
+ xmax=5000,
257
+ ymax=5000,
258
+ vmin=0,
259
+ fig=fig,
260
+ ax=axs[0],
261
+ ret_im=True,
262
+ title=None,
263
+ animated=True,
264
+ precalc=True,
265
+ )
266
+ next(ofg)
267
+
268
+ engine.finalize()
269
+
270
+ anim = foxes.output.Animator(fig)
271
+ anim.add_generator(ofg)
272
+ anim.add_generator(
273
+ o.gen_stdata(
274
+ turbines=[1, 4, 7],
275
+ variable=FV.REWS,
276
+ fig=fig,
277
+ ax=axs[1],
278
+ ret_im=True,
279
+ legloc="upper right",
280
+ animated=True,
281
+ )
282
+ )
283
+
284
+ ani = anim.animate()
285
+
286
+ lo = foxes.output.FarmLayoutOutput(farm)
287
+ lo.get_figure(
288
+ fig=fig,
289
+ ax=axs[0],
290
+ title="",
291
+ annotate=1,
292
+ anno_delx=-120,
293
+ anno_dely=-60,
294
+ alpha=0,
295
+ )
296
+
297
+ axs[0].scatter(
298
+ [args.ref_xy[0]],
299
+ [args.ref_xy[1]],
300
+ marker="x",
301
+ color="red",
302
+ s=80,
303
+ animated=True,
304
+ )
305
+
306
+ fpath = Path(args.ani_file)
307
+ print("Writing file", fpath)
308
+ if fpath.suffix == ".gif":
309
+ ani.save(filename=fpath, writer="pillow", fps=args.fps)
310
+ else:
311
+ ani.save(filename=fpath, writer="ffmpeg", fps=args.fps)
@@ -0,0 +1,121 @@
1
+ import time
2
+ import argparse
3
+ import matplotlib.pyplot as plt
4
+ import numpy as np
5
+
6
+ import foxes
7
+ import foxes.variables as FV
8
+
9
+
10
+ if __name__ == "__main__":
11
+ parser = argparse.ArgumentParser()
12
+ parser.add_argument(
13
+ "-f",
14
+ "--file_pattern",
15
+ help="The search pattern for input *.nc files",
16
+ default="data/data_*.nc",
17
+ )
18
+ parser.add_argument(
19
+ "-t",
20
+ "--turbine_file",
21
+ help="The P-ct-curve csv file (path or static)",
22
+ default="NREL-5MW-D126-H90.csv",
23
+ )
24
+ parser.add_argument("-r", "--rotor", help="The rotor model", default="centre")
25
+ parser.add_argument(
26
+ "-p", "--pwakes", help="The partial wakes models", default="centre", nargs="+"
27
+ )
28
+ parser.add_argument(
29
+ "-w",
30
+ "--wakes",
31
+ help="The wake models",
32
+ default=["Jensen_linear_k007"],
33
+ nargs="+",
34
+ )
35
+ parser.add_argument(
36
+ "-wf", "--wake_frame", help="The wake frame choice", default="rotor_wd"
37
+ )
38
+ parser.add_argument(
39
+ "-m", "--tmodels", help="The turbine models", default=[], nargs="+"
40
+ )
41
+ parser.add_argument(
42
+ "-nt", "--n_turbines", help="The number of turbines", default=9, type=int
43
+ )
44
+ parser.add_argument("-e", "--engine", help="The engine", default="ProcessEngine")
45
+ parser.add_argument(
46
+ "-n", "--n_cpus", help="The number of cpus", default=None, type=int
47
+ )
48
+ parser.add_argument(
49
+ "-c",
50
+ "--chunksize_states",
51
+ help="The chunk size for states",
52
+ default=None,
53
+ type=int,
54
+ )
55
+ parser.add_argument(
56
+ "-C",
57
+ "--chunksize_points",
58
+ help="The chunk size for points",
59
+ default=None,
60
+ type=int,
61
+ )
62
+ parser.add_argument(
63
+ "-npl", "--no_pre_load", help="Do not pre-load data", action="store_true"
64
+ )
65
+ parser.add_argument(
66
+ "-nf", "--nofig", help="Do not show figures", action="store_true"
67
+ )
68
+ args = parser.parse_args()
69
+
70
+ states = foxes.input.states.FieldDataNC(
71
+ args.file_pattern,
72
+ output_vars=[FV.WS, FV.WD, FV.TI, FV.RHO],
73
+ # var2ncvar={FV.WS: "ws", FV.WD: "wd", FV.TI: "ti"},
74
+ fixed_vars={FV.RHO: 1.225},
75
+ pre_load=not args.no_pre_load,
76
+ )
77
+
78
+ mbook = foxes.models.ModelBook()
79
+ ttype = foxes.models.turbine_types.PCtFile(args.turbine_file)
80
+ mbook.turbine_types[ttype.name] = ttype
81
+
82
+ farm = foxes.WindFarm()
83
+ N = int(args.n_turbines**0.5)
84
+ foxes.input.farm_layout.add_grid(
85
+ farm,
86
+ xy_base=np.array([500.0, 500.0]),
87
+ step_vectors=np.array([[500.0, 0], [0, 500.0]]),
88
+ steps=(N, N),
89
+ turbine_models=args.tmodels + [ttype.name],
90
+ )
91
+
92
+ algo = foxes.algorithms.Downwind(
93
+ farm,
94
+ states,
95
+ wake_models=args.wakes,
96
+ rotor_model=args.rotor,
97
+ wake_frame=args.wake_frame,
98
+ partial_wakes=args.pwakes,
99
+ mbook=mbook,
100
+ engine=args.engine,
101
+ n_procs=args.n_cpus,
102
+ chunk_size_states=args.chunksize_states,
103
+ chunk_size_points=args.chunksize_points,
104
+ verbosity=1,
105
+ )
106
+
107
+ time0 = time.time()
108
+ farm_results = algo.calc_farm()
109
+ time1 = time.time()
110
+
111
+ print("\nCalc time =", time1 - time0, "\n")
112
+
113
+ print(farm_results)
114
+
115
+ fr = farm_results.to_dataframe()
116
+ print(fr[[FV.WD, FV.AMB_REWS, FV.REWS, FV.AMB_P, FV.P]])
117
+
118
+ if not args.nofig:
119
+ o = foxes.output.FlowPlots2D(algo, farm_results)
120
+ o.get_mean_fig_xy(FV.WS, resolution=10)
121
+ plt.show()
@@ -0,0 +1,201 @@
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
+ if __name__ == "__main__":
9
+ # define arguments and options:
10
+ parser = argparse.ArgumentParser()
11
+ parser.add_argument("--ws", help="The wind speed", type=float, default=9.0)
12
+ parser.add_argument("--wd", help="The wind direction", type=float, default=270.0)
13
+ parser.add_argument("--ti", help="The TI value", type=float, default=0.08)
14
+ parser.add_argument("--rho", help="The air density", type=float, default=1.225)
15
+ parser.add_argument(
16
+ "-dx", help="The turbine spacing in x", type=float, default=800.0
17
+ )
18
+ parser.add_argument(
19
+ "-dy", help="The turbine spacing in y", type=float, default=400.0
20
+ )
21
+ parser.add_argument(
22
+ "-nx", help="The number of turbines in x direction", type=int, default=6
23
+ )
24
+ parser.add_argument(
25
+ "-ny", help="The number of turbines in y direction", type=int, default=10
26
+ )
27
+ parser.add_argument(
28
+ "-t",
29
+ "--turbine_file",
30
+ help="The P-ct-curve csv file (path or static)",
31
+ default="NREL-5MW-D126-H90.csv",
32
+ )
33
+ parser.add_argument(
34
+ "-m", "--tmodels", help="The turbine models", default=[], nargs="+"
35
+ )
36
+ parser.add_argument(
37
+ "-w",
38
+ "--wakes",
39
+ help="The wake models",
40
+ default=["RHB", "Bastankhah2014_linear_lim_k004"],
41
+ nargs="+",
42
+ )
43
+ parser.add_argument("-r", "--rotor", help="The rotor model", default="centre")
44
+ parser.add_argument(
45
+ "-p", "--pwakes", help="The partial wakes models", default=None, nargs="+"
46
+ )
47
+ parser.add_argument("-f", "--frame", help="The wake frame", default="rotor_wd")
48
+ parser.add_argument("-v", "--var", help="The plot variable", default=FV.WS)
49
+ parser.add_argument("-e", "--engine", help="The engine", default=None)
50
+ parser.add_argument(
51
+ "-nit",
52
+ "--not_iterative",
53
+ help="Don't use the iterative algorithm",
54
+ action="store_true",
55
+ )
56
+ parser.add_argument(
57
+ "-nf", "--nofig", help="Do not show figures", action="store_true"
58
+ )
59
+ args = parser.parse_args()
60
+
61
+ # create model book
62
+ mbook = foxes.ModelBook()
63
+ ttype = foxes.models.turbine_types.PCtFile(args.turbine_file)
64
+ mbook.turbine_types[ttype.name] = ttype
65
+
66
+ # create states
67
+ states = foxes.input.states.SingleStateStates(
68
+ ws=args.ws, wd=args.wd, ti=args.ti, rho=args.rho
69
+ )
70
+
71
+ # create wind farm
72
+ print("\nCreating wind farm")
73
+ farm = foxes.WindFarm()
74
+ foxes.input.farm_layout.add_grid(
75
+ farm=farm,
76
+ xy_base=[0.0, 0.0],
77
+ step_vectors=[[args.dx, 0.0], [0.0, args.dy]],
78
+ steps=[args.nx, args.ny],
79
+ turbine_models=["DTU10MW"],
80
+ verbosity=0,
81
+ )
82
+
83
+ # create algorithm
84
+ Algo = (
85
+ foxes.algorithms.Downwind if args.not_iterative else foxes.algorithms.Iterative
86
+ )
87
+ algo = Algo(
88
+ farm,
89
+ states,
90
+ rotor_model=args.rotor,
91
+ wake_models=args.wakes,
92
+ wake_frame=args.frame,
93
+ partial_wakes=args.pwakes,
94
+ mbook=mbook,
95
+ engine=args.engine,
96
+ verbosity=1,
97
+ )
98
+
99
+ # calculate farm results
100
+ farm_results = algo.calc_farm()
101
+ print("\nResults data:\n", farm_results)
102
+
103
+ # add capacity and efficiency to farm results
104
+ o = foxes.output.FarmResultsEval(farm_results)
105
+ o.add_capacity(algo)
106
+ o.add_capacity(algo, ambient=True)
107
+ o.add_efficiency()
108
+
109
+ # state-turbine results
110
+ farm_df = farm_results.to_dataframe()
111
+ print("\nFarm results data:\n")
112
+ print(
113
+ farm_df[
114
+ [
115
+ FV.X,
116
+ FV.WD,
117
+ FV.AMB_REWS,
118
+ FV.REWS,
119
+ FV.AMB_TI,
120
+ FV.TI,
121
+ FV.AMB_P,
122
+ FV.P,
123
+ FV.CT,
124
+ FV.EFF,
125
+ ]
126
+ ]
127
+ )
128
+ print()
129
+
130
+ # results by turbine
131
+ turbine_results = o.reduce_states(
132
+ {
133
+ FV.AMB_P: "mean",
134
+ FV.P: "mean",
135
+ FV.AMB_CAP: "mean",
136
+ FV.CAP: "mean",
137
+ FV.EFF: "mean",
138
+ }
139
+ )
140
+ turbine_results[FV.AMB_YLD] = o.calc_turbine_yield(
141
+ algo=algo, annual=True, ambient=True
142
+ )
143
+ turbine_results[FV.YLD] = o.calc_turbine_yield(algo=algo, annual=True)
144
+ print("\nResults by turbine:\n")
145
+ print(turbine_results)
146
+
147
+ # power results
148
+ P0 = o.calc_mean_farm_power(ambient=True)
149
+ P = o.calc_mean_farm_power()
150
+ print(f"\nFarm power : {P/1000:.1f} MW")
151
+ print(f"Farm ambient power: {P0/1000:.1f} MW")
152
+ print(f"Farm efficiency : {o.calc_farm_efficiency()*100:.2f} %")
153
+ print(f"Annual farm yield : {turbine_results[FV.YLD].sum():.2f} GWh.")
154
+
155
+ # horizontal flow plot
156
+ if not args.nofig:
157
+ o = foxes.output.FlowPlots2D(algo, farm_results)
158
+ xmin = -2000
159
+ xmax = (args.nx - 1) * args.dx + 2000
160
+ g = o.gen_states_fig_xy(
161
+ args.var,
162
+ figsize=(7, 5),
163
+ resolution=20,
164
+ xmin=xmin,
165
+ xmax=xmax,
166
+ yspace=1000.0,
167
+ levels=40,
168
+ rotor_color="black",
169
+ )
170
+ fig = next(g)
171
+ plt.show()
172
+ plt.close(fig)
173
+
174
+ # center line plot:
175
+ H = mbook.turbine_types[ttype.name].H
176
+ n_points = 10000
177
+ points = np.zeros((1, n_points, 3))
178
+ points[:, :, 0] = np.linspace(xmin, xmax, n_points)[None, :]
179
+ points[:, :, 2] = H
180
+ point_results = algo.calc_points(farm_results, points)
181
+ fig, ax = plt.subplots(figsize=(10, 5))
182
+ ax.plot(points[0, :, 0], point_results[FV.WS][0, :])
183
+ ax.set_xlabel("x [m]")
184
+ ax.set_ylabel("Wind speed [m/s]")
185
+ plt.show()
186
+ plt.close(fig)
187
+
188
+ # front line plot:
189
+ points = np.zeros((1, n_points, 3))
190
+ points[:, :, 0] = -200
191
+ points[:, :, 1] = np.linspace(-500.0, args.ny * args.dy + 500, n_points)[
192
+ None, :
193
+ ]
194
+ points[:, :, 2] = H
195
+ point_results = algo.calc_points(farm_results, points)
196
+ fig, ax = plt.subplots(figsize=(10, 5))
197
+ ax.plot(point_results[FV.WS][0, :], points[0, :, 1])
198
+ ax.set_ylabel("y [m]")
199
+ ax.set_xlabel("Wind speed [m/s]")
200
+ plt.show()
201
+ plt.close(fig)