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.

../_images/spinup_magnitude_of_velocity_timestep_14400.png

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 line

  • We are now saving boundary condition data, using the ABL.bndry* lines

  • Because 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