Precursor (ABL) walkthrough
With AMR-Wind compiled, we can run simulations. In this section, we will run two simulations of a weakly convective atmospheric boundary layer. The first simulation will be of a transient “spinup” phase, and the second simulation will serve as a “precursor” for a turbine simulation.
Before simulating anything, we first need to set up the input file. This
is a text file, and its filename traditionally ends with .inp
. There are generally two approaches to
set one up: manually through a text editor, often beginning with an example file as a starting point,
or with the use of amr-wind-frontend. For larger
simulations, with many turbines and refinement zones, amr-wind-frontend is the ideal approach for
input-file setup. This tool shows the locations of the turbines and refinements, providing a great
sanity check for expensive simulations. For simpler simulations, with one or a handful of turbines,
the manual approach is typically sufficient when beginning from a valid starting point. If you do not
have an input file on hand to use as a template, input files from the regression tests directory
(“test/test_files/”) in the AMR-Wind repository can serve as examples. Please consult the
input file reference to understand and appropriately modify the available input arguments.
Spinup simulation
Here is the content of our spinup input file:
1#¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨#
2# SIMULATION CONTROL #
3#.......................................#
4time.stop_time = 7200.0 # Max (simulated) time to evolve [s]
5time.max_step = -1 # Max number of time steps; -1 means termination set by timestamps
6time.fixed_dt = 0.5 # Use this constant dt if > 0
7time.cfl = 0.95 # CFL factor, will produce warnings if exceeded using fixed_dt
8
9time.plot_interval = 1800 # Steps between plot files
10time.checkpoint_interval = 1800 # Steps between checkpoint files
11
12incflo.physics = ABL
13turbulence.model = OneEqKsgsM84 # For neutral ABL, use "Smagorinsky"
14TKE.source_terms = KsgsM84Src
15incflo.gravity = 0. 0. -9.81 # Gravitational force (3D)
16incflo.density = 1.225 # Reference density; make sure this agrees with OpenFAST values
17transport.viscosity = 1.0e-5 # Dynamic viscosity [N-s/m^2]
18transport.laminar_prandtl = 0.7
19transport.turbulent_prandtl = 0.3333
20
21#¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨#
22# GEOMETRY & BCs #
23#.......................................#
24geometry.prob_lo = 0. 0. 0. # Lo corner coordinates
25geometry.prob_hi = 2560. 2560. 1280. # Hi corner coordinates
26amr.n_cell = 128 128 64 # Grid cells at coarsest AMRlevel
27amr.max_level = 0 # Max AMR level in hierarchy
28geometry.is_periodic = 1 1 0 # Periodicity x y z (0/1)
29
30zlo.type = wall_model
31zhi.type = slip_wall
32zhi.temperature_type = fixed_gradient
33zhi.temperature = 0.003
34
35#¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨#
36# PHYSICS #
37#.......................................#
38ICNS.source_terms = BoussinesqBuoyancy CoriolisForcing ABLForcing
39incflo.velocity = 10.0 0.0 0.0
40ABLForcing.abl_forcing_height = 86.5
41CoriolisForcing.latitude = 36.607322 # Southern Great Plains
42CoriolisForcing.north_vector = 0.0 1.0 0.0
43CoriolisForcing.east_vector = 1.0 0.0 0.0
44BoussinesqBuoyancy.reference_temperature = 290.0
45ABL.reference_temperature = 290.0
46ABL.temperature_heights = 0.0 600.0 700.0 1700.0 # Make sure top height >= the domain height
47ABL.temperature_values = 290.0 290.0 298.0 301.0
48ABL.perturb_temperature = true
49ABL.cutoff_height = 50.0
50ABL.perturb_velocity = true
51ABL.perturb_ref_height = 50.0
52ABL.Uperiods = 4.0
53ABL.Vperiods = 4.0
54ABL.deltaU = 1.0
55ABL.deltaV = 1.0
56ABL.kappa = .40
57ABL.surface_roughness_z0 = 0.01 # [m]
58ABL.surface_temp_flux = 0.05 # Surface temperature flux [K-m/s]
59
60#¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨#
61# POST-Processing #
62#.......................................#
63incflo.post_processing = sampling
64
65# --- Sampling parameters ---
66sampling.output_frequency = 900
67sampling.fields = velocity temperature
68
69#---- sample defs ----
70sampling.labels = xy-domain xz-domain
71
72sampling.xy-domain.type = PlaneSampler
73sampling.xy-domain.num_points = 256 256
74sampling.xy-domain.origin = 0.0 0.0 86.5
75sampling.xy-domain.axis1 = 2550.0 0.0 0.0
76sampling.xy-domain.axis2 = 0.0 2550.0 0.0
77sampling.xy-domain.offset_vector = 0.0 0.0 1.0
78sampling.xy-domain.offsets = -63.45 0.0 63.45
79
80sampling.xz-domain.type = PlaneSampler
81sampling.xz-domain.num_points = 256 128
82sampling.xz-domain.origin = 0.0 1280.0 0.0
83sampling.xz-domain.axis1 = 2550.0 0.0 0.0
84sampling.xz-domain.axis2 = 0.0 0.0 1270.0
Further details about some input arguments
ABLForcing is the source term that pushes the flow field to a target
velocity. That target velocity is specified by incflo.velocity
.
The ABLForcing vector term is proportional to the difference between
the target velocity and the xy-planar average velocity at the
abl_forcing_height
. The ABLForcing term is applied uniformly to
the entire domain and is intended to mimic the atmospheric pressure
gradient in the context of a periodic domain.
BoussinesqBuoyancy implements the effect of buoyancy based on differences between the local temperature and a reference temperature. CoriolisForcing represents the effect of the rotation of the earth on the flow field.
Predominantly, the ABL
arguments refer to details of the initial
conditions, which also allow for perturbations designed to trip the onset
of turbulence. However, the surface_
details and the kappa
value inform the wall model at the lower boundary.
We are going to run the spinup simulation for a duration of two hours. The spinup simulation features a fairly small domain with a coarse uniform grid resolution of 20 m and does not employ any grid refinement.
When running simulations on a cluster, please follow the etiquette expected on the machine, which is typically to use a scratch directory as the active directory during a simulation run. In that context, you will also need a submission script. Please consult the user manual of your cluster to design such a script properly.
Here are a few tips for submitting an AMR-Wind run. If you used a Spack environment to compile
amr-wind, it is easiest to reference the amr-wind executable by activating Spack, activating the environment, and then using
the command spack load amr-wind
to have the correct executable available without needing to specify its full path. Finally,
the syntax of the amr-wind command looks like
amr_wind spinup.inp
which should follow after an srun
or mpiexec
command (or similar) in a submission script to take advantage of parallelization.
This particular simulation has about 1 million cells, which means that it is suited run with about 50-80 CPU ranks.
If the simulation completes, the last time step reported will be 14400 at time 7200 s, and the job directory will contain
checkpoint (chk*) and plotfile (plt*) directories, along with a post_processing/ directory. Once the spinup simulation is done,
it is helpful to sanity check that the flow field variables make sense. The plt#####
files can be opened using Paraview or other
visualization software that is AMReX-compatible. Another quick test is to plot the evolution of horizontally averaged vertical profiles,
which are provided through the abl_statistics
file within post_processing/.
As an example, here we use Paraview and display the magnitude of the velocity at the final time of the simulation.
Precursor simulation
After sufficiently spinning up turbulence, the “precursor simulation” follows. In the context of wind turbine LES, a precursor is a simulation that is run without a turbine for the explicit purpose of generating inflow boundary conditions. For computational efficiency, spinup and precursor simulations are almost always run with periodic boundary conditions. This means wind that exits the outflow simulation is then recirculated back into the inflow, which is a fine assumption for a statistically homogeneous atmosphere. However, this is problematic when wind turbines are present—turbines generate wakes, and these should not recirculate back to upstream of the turbine. So we run wind turbine simulations with a prescribed “inflow boundary condition” (where the wind data comes from the precursor) and an “outflow boundary condition” (usually a pressure BC).
Here is the content of the precursor simulation.
1#¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨#
2# SIMULATION CONTROL #
3#.......................................#
4time.stop_time = 7800.0 # Max (simulated) time to evolve [s]
5time.max_step = -1 # Max number of time steps; -1 means termination set by timestamps
6time.fixed_dt = 0.125 # Use this constant dt if > 0
7time.cfl = 0.95 # CFL factor
8
9time.plot_interval = 1200 # Steps between plot files
10time.checkpoint_interval = 1200 # Steps between checkpoint files
11ABL.bndry_file = bndry_file.native
12ABL.bndry_io_mode = 0 # 0 = write, 1 = read
13ABL.bndry_planes = xlo
14ABL.bndry_output_start_time = 7200.0
15ABL.bndry_var_names = velocity temperature tke
16
17incflo.physics = ABL
18io.restart_file = ../spinup/chk14400
19turbulence.model = OneEqKsgsM84 # For neutral ABL, use "Smagorinsky"
20TKE.source_terms = KsgsM84Src
21incflo.gravity = 0. 0. -9.81 # Gravitational force (3D)
22incflo.density = 1.225 # Reference density; make sure this agrees with OpenFAST values
23transport.viscosity = 1.0e-5 # Dynamic viscosity [N-s/m^2]
24transport.laminar_prandtl = 0.7
25transport.turbulent_prandtl = 0.3333
26
27#¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨#
28# GEOMETRY & BCs #
29#.......................................#
30geometry.prob_lo = 0. 0. 0. # Lo corner coordinates
31geometry.prob_hi = 2560. 2560. 1280. # Hi corner coordinates
32amr.n_cell = 128 128 64 # Grid cells at coarsest AMRlevel
33amr.max_level = 0 # Max AMR level in hierarchy
34geometry.is_periodic = 1 1 0 # Periodicity x y z (0/1)
35
36zlo.type = wall_model
37zhi.type = slip_wall
38zhi.temperature_type = fixed_gradient
39zhi.temperature = 0.003
40
41#¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨#
42# PHYSICS #
43#.......................................#
44ICNS.source_terms = BoussinesqBuoyancy CoriolisForcing ABLForcing
45incflo.velocity = 10.0 0.0 0.0
46ABLForcing.abl_forcing_height = 86.5
47ABLForcing.forcing_timetable_output_file = abl_forces.txt
48CoriolisForcing.latitude = 36.607322 # Southern Great Plains
49CoriolisForcing.north_vector = 0.0 1.0 0.0
50CoriolisForcing.east_vector = 1.0 0.0 0.0
51BoussinesqBuoyancy.reference_temperature = 290.0
52ABL.reference_temperature = 290.0
53ABL.temperature_heights = 0.0 600.0 700.0 1700.0 # Make sure top height >= the domain height
54ABL.temperature_values = 290.0 290.0 298.0 301.0
55ABL.perturb_temperature = true
56ABL.cutoff_height = 50.0
57ABL.perturb_velocity = true
58ABL.perturb_ref_height = 50.0
59ABL.Uperiods = 4.0
60ABL.Vperiods = 4.0
61ABL.deltaU = 1.0
62ABL.deltaV = 1.0
63ABL.kappa = .40
64ABL.surface_roughness_z0 = 0.01 # [m]
65ABL.surface_temp_flux = 0.05 # Surface temperature flux [K-m/s]
66
67#¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨#
68# POST-Processing #
69#.......................................#
70incflo.post_processing = sampling averaging
71
72# --- Sampling parameters ---
73sampling.output_frequency = 96
74sampling.fields = velocity temperature
75
76#---- sample defs ----
77sampling.labels = xy-domain xz-domain
78
79sampling.xy-domain.type = PlaneSampler
80sampling.xy-domain.num_points = 256 256
81sampling.xy-domain.origin = 0.0 0.0 86.5
82sampling.xy-domain.axis1 = 2550.0 0.0 0.0
83sampling.xy-domain.axis2 = 0.0 2550.0 0.0
84sampling.xy-domain.offset_vector = 0.0 0.0 1.0
85sampling.xy-domain.offsets = -63.45 0.0 63.45
86
87sampling.xz-domain.type = PlaneSampler
88sampling.xz-domain.num_points = 256 128
89sampling.xz-domain.origin = 0.0 1280.0 0.0
90sampling.xz-domain.axis1 = 2550.0 0.0 0.0
91sampling.xz-domain.axis2 = 0.0 0.0 1270.0
92
93#¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨#
94# AVERAGING #
95#.......................................#
96averaging.type = TimeAveraging
97averaging.labels = means stress
98
99averaging.averaging_window = 60.0
100averaging.averaging_start_time = 7200.0
101
102averaging.means.fields = velocity
103averaging.means.averaging_type = ReAveraging
104
105averaging.stress.fields = velocity
106averaging.stress.averaging_type = ReynoldsStress
- This file is almost identical to the spinup input file, except there are a few differences:
This simulation starts from the last timestep of the spinup simulation, using the
io.restart_file
lineWe are now saving boundary condition data, using the
ABL.bndry*
linesBecause the simulation after the precursor (inflow-outflow simulation with turbines) will have a much finer mesh, it will also require a smaller timestep, reduced by a factor of 4 to 0.125 seconds. Reducing the timestep in the precursor simulation as well (the
time.fixed_dt
line) permits the boundary plane and body force data to have better temporal resolution. This modification is not required for the precursor, though; this workflow will still function fine with an unmodified precursor time step.For more detailed analysis in post-processing, the frequency of
sampling.output_frequency
is increased. This argument actually refers to the output interval, so a smaller number means files are written more often.
Go to the next step: Turbine simulation walkthrough