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.
- docs/source/conf.py +353 -0
- examples/abl_states/run.py +160 -0
- examples/compare_rotors_pwakes/run.py +217 -0
- examples/compare_wakes/run.py +241 -0
- examples/dyn_wakes/run.py +311 -0
- examples/field_data_nc/run.py +121 -0
- examples/induction_RHB/run.py +201 -0
- examples/multi_height/run.py +113 -0
- examples/power_mask/run.py +249 -0
- examples/random_timeseries/run.py +210 -0
- examples/scan_row/run.py +193 -0
- examples/sector_management/run.py +162 -0
- examples/sequential/run.py +209 -0
- examples/single_state/run.py +201 -0
- examples/states_lookup_table/run.py +137 -0
- examples/streamline_wakes/run.py +138 -0
- examples/tab_file/run.py +142 -0
- examples/timelines/run.py +267 -0
- examples/timeseries/run.py +183 -0
- examples/timeseries_slurm/run.py +185 -0
- examples/wind_rose/run.py +141 -0
- examples/windio/run.py +29 -0
- examples/yawed_wake/run.py +196 -0
- foxes/__init__.py +4 -8
- foxes/algorithms/__init__.py +1 -1
- foxes/algorithms/downwind/downwind.py +232 -101
- foxes/algorithms/downwind/models/farm_wakes_calc.py +11 -6
- foxes/algorithms/downwind/models/init_farm_data.py +1 -1
- foxes/algorithms/downwind/models/point_wakes_calc.py +5 -6
- foxes/algorithms/downwind/models/reorder_farm_output.py +0 -1
- foxes/algorithms/downwind/models/set_amb_point_results.py +4 -2
- foxes/algorithms/iterative/iterative.py +73 -33
- foxes/algorithms/iterative/models/farm_wakes_calc.py +11 -6
- foxes/algorithms/sequential/models/plugin.py +1 -1
- foxes/algorithms/sequential/sequential.py +126 -255
- foxes/constants.py +17 -2
- foxes/core/__init__.py +1 -0
- foxes/core/algorithm.py +631 -146
- foxes/core/data.py +252 -20
- foxes/core/data_calc_model.py +13 -289
- foxes/core/engine.py +630 -0
- foxes/core/farm_controller.py +37 -9
- foxes/core/farm_data_model.py +15 -0
- foxes/core/model.py +133 -80
- foxes/core/point_data_model.py +15 -0
- foxes/core/rotor_model.py +27 -21
- foxes/core/states.py +16 -0
- foxes/core/turbine_type.py +28 -0
- foxes/core/wake_frame.py +22 -4
- foxes/core/wake_model.py +2 -3
- foxes/data/windio/windio_5turbines_timeseries.yaml +23 -1
- foxes/engines/__init__.py +16 -0
- foxes/engines/dask.py +975 -0
- foxes/engines/default.py +75 -0
- foxes/engines/futures.py +72 -0
- foxes/engines/mpi.py +38 -0
- foxes/engines/multiprocess.py +74 -0
- foxes/engines/numpy.py +185 -0
- foxes/engines/pool.py +263 -0
- foxes/engines/single.py +139 -0
- foxes/input/farm_layout/__init__.py +1 -0
- foxes/input/farm_layout/from_csv.py +4 -0
- foxes/input/farm_layout/from_json.py +1 -1
- foxes/input/farm_layout/grid.py +2 -2
- foxes/input/farm_layout/ring.py +65 -0
- foxes/input/farm_layout/row.py +2 -2
- foxes/input/states/__init__.py +6 -0
- foxes/input/states/create/random_abl_states.py +1 -1
- foxes/input/states/field_data_nc.py +157 -32
- foxes/input/states/multi_height.py +127 -13
- foxes/input/states/one_point_flow.py +577 -0
- foxes/input/states/scan_ws.py +73 -2
- foxes/input/states/states_table.py +204 -35
- foxes/input/windio/__init__.py +1 -1
- foxes/input/windio/get_states.py +44 -23
- foxes/input/windio/read_attributes.py +41 -16
- foxes/input/windio/read_farm.py +116 -102
- foxes/input/windio/read_fields.py +13 -6
- foxes/input/windio/read_outputs.py +63 -22
- foxes/input/windio/runner.py +31 -17
- foxes/input/windio/windio.py +36 -22
- foxes/models/ground_models/wake_mirror.py +8 -4
- foxes/models/model_book.py +29 -18
- foxes/models/partial_wakes/rotor_points.py +3 -3
- foxes/models/rotor_models/centre.py +4 -0
- foxes/models/rotor_models/grid.py +22 -23
- foxes/models/rotor_models/levels.py +4 -5
- foxes/models/turbine_models/calculator.py +0 -2
- foxes/models/turbine_models/lookup_table.py +27 -2
- foxes/models/turbine_models/rotor_centre_calc.py +4 -3
- foxes/models/turbine_models/set_farm_vars.py +103 -34
- foxes/models/turbine_types/PCt_file.py +24 -0
- foxes/models/turbine_types/PCt_from_two.py +24 -0
- foxes/models/turbine_types/__init__.py +1 -0
- foxes/models/turbine_types/lookup.py +316 -0
- foxes/models/turbine_types/null_type.py +50 -0
- foxes/models/turbine_types/wsrho2PCt_from_two.py +24 -0
- foxes/models/turbine_types/wsti2PCt_from_two.py +24 -0
- foxes/models/vertical_profiles/data_profile.py +1 -1
- foxes/models/wake_frames/__init__.py +1 -0
- foxes/models/wake_frames/dynamic_wakes.py +424 -0
- foxes/models/wake_frames/farm_order.py +23 -3
- foxes/models/wake_frames/rotor_wd.py +4 -2
- foxes/models/wake_frames/seq_dynamic_wakes.py +56 -63
- foxes/models/wake_frames/streamlines.py +19 -20
- foxes/models/wake_frames/timelines.py +328 -127
- foxes/models/wake_frames/yawed_wakes.py +4 -1
- foxes/models/wake_models/dist_sliced.py +1 -3
- foxes/models/wake_models/induction/rankine_half_body.py +4 -4
- foxes/models/wake_models/induction/rathmann.py +2 -2
- foxes/models/wake_models/induction/self_similar.py +2 -2
- foxes/models/wake_models/induction/vortex_sheet.py +2 -2
- foxes/models/wake_models/ti/iec_ti.py +34 -17
- foxes/models/wake_models/top_hat.py +1 -1
- foxes/models/wake_models/wind/bastankhah14.py +2 -2
- foxes/models/wake_models/wind/bastankhah16.py +8 -7
- foxes/models/wake_models/wind/jensen.py +1 -1
- foxes/models/wake_models/wind/turbopark.py +2 -2
- foxes/output/__init__.py +4 -1
- foxes/output/farm_layout.py +2 -2
- foxes/output/flow_plots_2d/__init__.py +0 -1
- foxes/output/flow_plots_2d/flow_plots.py +70 -30
- foxes/output/grids.py +91 -21
- foxes/output/seq_plugins/__init__.py +2 -0
- foxes/output/{flow_plots_2d → seq_plugins}/seq_flow_ani_plugin.py +62 -20
- foxes/output/seq_plugins/seq_wake_debug_plugin.py +145 -0
- foxes/output/slice_data.py +131 -111
- foxes/output/state_turbine_map.py +18 -13
- foxes/output/state_turbine_table.py +19 -19
- foxes/utils/__init__.py +1 -1
- foxes/utils/dev_utils.py +42 -0
- foxes/utils/dict.py +1 -1
- foxes/utils/factory.py +147 -52
- foxes/utils/pandas_helpers.py +4 -3
- foxes/utils/wind_dir.py +0 -2
- foxes/utils/xarray_utils.py +23 -13
- foxes/variables.py +37 -0
- {foxes-0.8.2.dist-info → foxes-1.0.dist-info}/METADATA +71 -33
- foxes-1.0.dist-info/RECORD +307 -0
- {foxes-0.8.2.dist-info → foxes-1.0.dist-info}/WHEEL +1 -1
- foxes-1.0.dist-info/top_level.txt +4 -0
- tests/0_consistency/iterative/test_iterative.py +92 -0
- tests/0_consistency/partial_wakes/test_partial_wakes.py +90 -0
- tests/1_verification/flappy_0_6/PCt_files/flappy/run.py +85 -0
- tests/1_verification/flappy_0_6/PCt_files/test_PCt_files.py +103 -0
- tests/1_verification/flappy_0_6/abl_states/flappy/run.py +85 -0
- tests/1_verification/flappy_0_6/abl_states/test_abl_states.py +87 -0
- tests/1_verification/flappy_0_6/partial_top_hat/flappy/run.py +82 -0
- tests/1_verification/flappy_0_6/partial_top_hat/test_partial_top_hat.py +82 -0
- tests/1_verification/flappy_0_6/row_Jensen_linear_centre/flappy/run.py +92 -0
- tests/1_verification/flappy_0_6/row_Jensen_linear_centre/test_row_Jensen_linear_centre.py +93 -0
- tests/1_verification/flappy_0_6/row_Jensen_linear_tophat/flappy/run.py +92 -0
- tests/1_verification/flappy_0_6/row_Jensen_linear_tophat/test_row_Jensen_linear_tophat.py +96 -0
- tests/1_verification/flappy_0_6/row_Jensen_linear_tophat_IECTI2005/flappy/run.py +94 -0
- tests/1_verification/flappy_0_6/row_Jensen_linear_tophat_IECTI2005/test_row_Jensen_linear_tophat_IECTI_2005.py +122 -0
- tests/1_verification/flappy_0_6/row_Jensen_linear_tophat_IECTI2019/flappy/run.py +94 -0
- tests/1_verification/flappy_0_6/row_Jensen_linear_tophat_IECTI2019/test_row_Jensen_linear_tophat_IECTI_2019.py +122 -0
- tests/1_verification/flappy_0_6/row_Jensen_quadratic_centre/flappy/run.py +92 -0
- tests/1_verification/flappy_0_6/row_Jensen_quadratic_centre/test_row_Jensen_quadratic_centre.py +93 -0
- tests/1_verification/flappy_0_6_2/grid_rotors/flappy/run.py +85 -0
- tests/1_verification/flappy_0_6_2/grid_rotors/test_grid_rotors.py +130 -0
- tests/1_verification/flappy_0_6_2/row_Bastankhah_Crespo/flappy/run.py +96 -0
- tests/1_verification/flappy_0_6_2/row_Bastankhah_Crespo/test_row_Bastankhah_Crespo.py +116 -0
- tests/1_verification/flappy_0_6_2/row_Bastankhah_linear_centre/flappy/run.py +93 -0
- tests/1_verification/flappy_0_6_2/row_Bastankhah_linear_centre/test_row_Bastankhah_linear_centre.py +99 -0
- tests/3_examples/test_examples.py +34 -0
- foxes/VERSION +0 -1
- foxes/output/flow_plots_2d.py +0 -0
- foxes/utils/runners/__init__.py +0 -1
- foxes/utils/runners/runners.py +0 -280
- foxes-0.8.2.dist-info/RECORD +0 -247
- foxes-0.8.2.dist-info/top_level.txt +0 -1
- foxes-0.8.2.dist-info/zip-safe +0 -1
- {foxes-0.8.2.dist-info → foxes-1.0.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()
|