Dynamic Wakes 3¶
Sequential wake propagation¶
For some applications it may be useful to run foxes
in state-by-state mode, i.e., without the benefits of state-wise chunking. For example, when coupling it to another simulation tool that runs based on an overall outer loop over the individual states.
For such cases the Sequential
algorithm has been added, which basically is an iterator over the states. Obviously this algorithm is much slower than the Downwind
or the Iterative
algorithms. On the plus side, for timeseries ambient states, it has the advantage that it can easily be combined with local propagation of wake parcels between two subsequent time stamps. This functionality is provided by the wake frame class SeqDynamicWakes
and does not require horizontal homogeneity.
The wake result is the same as for the DynamicWakes
wake frame, cf. a previous example, but now it has been computed in the context of state-by-state evaluation.
In [1]:
%matplotlib inline
import numpy as np
import matplotlib.pyplot as plt
plt.rcParams["animation.html"] = "jshtml"
import foxes
import foxes.variables as FV
We create a case with a regular 3 x 3 wind farm layout:
In [2]:
states = foxes.input.states.Timeseries(
data_source="timeseries_3000.csv.gz",
output_vars=[FV.WS, FV.WD, FV.TI, FV.RHO],
var2col={FV.WS: "WS", FV.WD: "WD", FV.TI: "TI", FV.RHO: "RHO"},
states_sel=range(230, 285),
)
farm = foxes.WindFarm()
foxes.input.farm_layout.add_grid(
farm,
xy_base=np.array([0.0, 0.0]),
step_vectors=np.array([[1000.0, 0], [0, 800.0]]),
steps=(3, 3),
turbine_models=["DTU10MW"],
verbosity=0,
)
algo = foxes.algorithms.Sequential(
farm,
states,
rotor_model="centre",
wake_models=["Bastankhah025_linear_loc_k004"],
wake_frame="seq_dyn_wakes_1min",
engine="numpy",
verbosity=0,
)
Notice that for the sake of drama, we artificially reset the time step to 1min
in the wake frame choice, more realistic would have been the choice seq_dyn_wakes
which is based on the true time delta of the time series.
Our goal in this example is the creation of an animation that shows the dynamics of the flow in a horizontal plane at hub height. With the Sequential
algorithm we can achieve this by treating the algo
object as a Python iterator, for example within a for
-loop.
Before doing so, we add a plugin that is evaluated whenever the iterator moves to the next state. In this case the plugin creates an image that is later on used for the animation:
In [3]:
# Add a plugin to the algorithm that updates
# an image for an animation with every time step:
anigen = foxes.output.SeqFlowAnimationPlugin(
orientation="xy",
var=FV.WS,
resolution=20,
levels=None,
quiver_pars=dict(scale=0.008, alpha=0.5),
quiver_n=111,
xmin=-5000,
ymin=-5000,
xmax=7000,
ymax=7000,
vmin=0,
vmax=10,
title=lambda si, s: f"t = {si:02d} min",
animated=True,
)
algo.plugins.append(anigen)
# Now run all states sequentially:
for r in algo:
print(algo.index)
print("\nFarm results:\n")
print(algo.farm_results)
# Create the animation:
fig, ax = plt.subplots()
anim = foxes.output.Animator(fig)
anim.add_generator(anigen.gen_images(ax=ax))
ani = anim.animate(interval=600)
lo = foxes.output.FarmLayoutOutput(farm)
lo.get_figure(
fig=fig,
ax=ax,
title="",
annotate=1,
anno_delx=-120,
anno_dely=-60,
alpha=0,
s=10,
)
plt.close()
print("done.")
print("Creating animation")
ani
2018-10-10T05:00:00.000000000
2018-10-10T06:00:00.000000000
2018-10-10T07:00:00.000000000
2018-10-10T08:00:00.000000000
2018-10-10T09:00:00.000000000
2018-10-10T10:00:00.000000000
2018-10-10T11:00:00.000000000
2018-10-10T12:00:00.000000000
2018-10-10T13:00:00.000000000
2018-10-10T14:00:00.000000000
2018-10-10T15:00:00.000000000
2018-10-10T16:00:00.000000000
2018-10-10T17:00:00.000000000
2018-10-10T18:00:00.000000000
2018-10-10T19:00:00.000000000
2018-10-10T20:00:00.000000000
2018-10-10T21:00:00.000000000
2018-10-10T22:00:00.000000000
2018-10-10T23:00:00.000000000
2018-10-11T00:00:00.000000000
2018-10-11T01:00:00.000000000
2018-10-11T02:00:00.000000000
2018-10-11T03:00:00.000000000
2018-10-11T04:00:00.000000000
2018-10-11T05:00:00.000000000
2018-10-11T06:00:00.000000000
2018-10-11T07:00:00.000000000
2018-10-11T08:00:00.000000000
2018-10-11T09:00:00.000000000
2018-10-11T10:00:00.000000000
2018-10-11T11:00:00.000000000
2018-10-11T12:00:00.000000000
2018-10-11T13:00:00.000000000
2018-10-11T14:00:00.000000000
2018-10-11T15:00:00.000000000
2018-10-11T16:00:00.000000000
2018-10-11T17:00:00.000000000
2018-10-11T18:00:00.000000000
2018-10-11T19:00:00.000000000
2018-10-11T20:00:00.000000000
2018-10-11T21:00:00.000000000
2018-10-11T22:00:00.000000000
2018-10-11T23:00:00.000000000
2018-10-12T00:00:00.000000000
2018-10-12T01:00:00.000000000
2018-10-12T02:00:00.000000000
2018-10-12T03:00:00.000000000
2018-10-12T04:00:00.000000000
2018-10-12T05:00:00.000000000
2018-10-12T06:00:00.000000000
2018-10-12T07:00:00.000000000
2018-10-12T08:00:00.000000000
2018-10-12T09:00:00.000000000
2018-10-12T10:00:00.000000000
2018-10-12T11:00:00.000000000
Farm results:
<xarray.Dataset> Size: 103kB
Dimensions: (state: 55, turbine: 9)
Coordinates:
* state (state) datetime64[ns] 440B 2018-10-10T05:00:00 ... 2018-10-1...
Dimensions without coordinates: turbine
Data variables: (12/27)
AMB_CT (state, turbine) float64 4kB 0.5443 0.5443 ... 0.814 0.814
AMB_P (state, turbine) float64 4kB 0.0 0.0 0.0 ... 8.506e+03 8.506e+03
AMB_REWS (state, turbine) float64 4kB 3.51 3.51 3.51 ... 10.52 10.52
AMB_REWS2 (state, turbine) float64 4kB 3.51 3.51 3.51 ... 10.52 10.52
AMB_REWS3 (state, turbine) float64 4kB 3.468 3.468 3.468 ... 10.51 10.51
AMB_RHO (state, turbine) float64 4kB 1.27 1.27 1.27 ... 1.23 1.23 1.23
... ...
YAW (state, turbine) float64 4kB 81.3 81.3 81.3 ... 54.28 54.28
order (state, turbine) int64 4kB 0 1 2 3 4 5 6 7 8 ... 1 2 3 4 5 6 7 8
order_inv (state, turbine) float64 4kB 0.0 1.0 2.0 3.0 ... 5.0 6.0 7.0 8.0
order_ssel (state, turbine) float64 4kB 0.0 0.0 0.0 0.0 ... 0.0 0.0 0.0 0.0
weight (state, turbine) float64 4kB 0.01818 0.01818 ... 0.01818 0.01818
tname (turbine) <U2 72B 'T0' 'T1' 'T2' 'T3' 'T4' 'T5' 'T6' 'T7' 'T8'
Creating animation data
done.
Creating animation
Out[3]: