Theory and Background¶
HONEE solves the time-dependent Navier-Stokes equations of compressible gas dynamics in a static Eulerian three-dimensional frame using unstructured high-order finite/spectral element spatial discretizations and explicit or implicit high-order time-stepping (available in PETSc). Moreover, the Navier-Stokes example has been developed using PETSc, so that the pointwise physics (defined at quadrature points) is separated from the parallelization and meshing concerns.
Advection-Diffusion¶
A simplified version of system (1), only accounting for the transport of total energy, is given by
with \(\bm{u}\) the vector velocity field and \(\kappa\) the diffusion coefficient. In this particular test case, a blob of total energy (defined by a characteristic radius \(r_c\)) is transported by two different wind types.
Rotation
In this case, a uniform circular velocity field transports the blob of total energy. We have solved (17) applying zero energy density \(E\), and no-flux for \(\bm{u}\) on the boundaries.
Translation
In this case, a background wind with a constant rectilinear velocity field, enters the domain and transports the blob of total energy out of the domain.
For the inflow boundary conditions, a prescribed \(E_{wind}\) is applied weakly on the inflow boundaries such that the weak form boundary integral in (5) is defined as
\[ \int_{\partial \Omega_{inflow}} \bm v \cdot \bm{F}(\bm q_N) \cdot \widehat{\bm{n}} \,dS = \int_{\partial \Omega_{inflow}} \bm v \, E_{wind} \, \bm u \cdot \widehat{\bm{n}} \,dS \, , \]For the outflow boundary conditions, we have used the current values of \(E\), following [PMK92] which extends the validity of the weak form of the governing equations to the outflow instead of replacing them with unknown essential or natural boundary conditions. The weak form boundary integral in (5) for outflow boundary conditions is defined as
\[ \int_{\partial \Omega_{outflow}} \bm v \cdot \bm{F}(\bm q_N) \cdot \widehat{\bm{n}} \,dS = \int_{\partial \Omega_{outflow}} \bm v \, E \, \bm u \cdot \widehat{\bm{n}} \,dS \, , \]
Isentropic Vortex¶
Three-dimensional Euler equations, which are simplified and nondimensionalized version of system (1) and account only for the convective fluxes, are given by
Following the setup given in [ZZS11], the mean flow for this problem is \(\rho=1\), \(P=1\), \(T=P/\rho= 1\) (Specific Gas Constant, \(R\), is 1), and \(\bm{u}=(u_1,u_2,0)\) while the perturbation \(\delta \bm{u}\), and \(\delta T\) are defined as
where \((\bar{x}, \, \bar{y}) = (x-x_c, \, y-y_c)\), \((x_c, \, y_c)\) represents the center of the domain, \(r^2=\bar{x}^2 + \bar{y}^2\), and \(\epsilon\) is the vortex strength (\(\epsilon\) < 10). There is no perturbation in the entropy \(S=P/\rho^\gamma\) (\(\delta S=0)\).
Shock Tube¶
This test problem is based on Sod’s Shock Tube (from[sod]), a canonical test case for discontinuity capturing in one dimension. For this problem, the three-dimensional Euler equations are formulated exactly as in the Isentropic Vortex problem. The default initial conditions are \(P=1\), \(\rho=1\) for the driver section and \(P=0.1\), \(\rho=0.125\) for the driven section. The initial velocity is zero in both sections. Symmetry boundary conditions are applied to the side walls and wall boundary conditions are applied at the end walls.
SU upwinding and discontinuity capturing have been implemented into the explicit timestepping operator for this problem. Discontinuity capturing is accomplished using a modified version of the \(YZ\beta\) operator described in [TS07]. This discontinuity capturing scheme involves the introduction of a dissipation term of the form
The shock capturing viscosity is implemented following the first formulation described in [TS07]. The characteristic velocity \(u_{cha}\) is taken to be the acoustic speed while the reference density \(\rho_{ref}\) is just the local density. Shock capturing viscosity is defined by the following
where,
\(\beta\) is a tuning parameter set between 1 (smoother shocks) and 2 (sharper shocks. The parameter \(h_{SHOCK}\) is a length scale that is proportional to the element length in the direction of the density gradient unit vector. This density gradient unit vector is defined as \(\hat{\bm j} = \frac{\nabla \rho}{|\nabla \rho|}\). The original formulation of Tezduyar and Senga relies on the shape function gradient to define the element length scale, but this gradient is not available to qFunctions in libCEED. To avoid this problem, \(h_{SHOCK}\) is defined in the current implementation as
where
The constant \(C_{YZB}\) is set to 0.1 for piecewise linear elements in the current implementation. Larger values approaching unity are expected with more robust stabilization and implicit timestepping.
Gaussian Wave¶
This test case is taken/inspired by that presented in [MDGP+14]. It is intended to test non-reflecting/Riemann boundary conditions. It’s primarily intended for Euler equations, but has been implemented for the Navier-Stokes equations here for flexibility.
The problem has a perturbed initial condition and lets it evolve in time. The initial condition contains a Gaussian perturbation in the pressure field:
where \(A\) and \(\sigma\) are the amplitude and width of the perturbation, respectively, and \((\bar{x}, \bar{y}) = (x-x_e, y-y_e)\) is the distance to the epicenter of the perturbation, \((x_e, y_e)\). The simulation produces a strong acoustic wave and leaves behind a cold thermal bubble that advects at the fluid velocity.
The boundary conditions are freestream in the x and y directions. When using an HLL (Harten, Lax, van Leer) Riemann solver [Tor09] (option -freestream_riemann hll
), the acoustic waves exit the domain cleanly, but when the thermal bubble reaches the boundary, it produces strong thermal oscillations that become acoustic waves reflecting into the domain.
This problem can be fixed using a more sophisticated Riemann solver such as HLLC [Tor09] (option -freestream_riemann hllc
, which is default), which is a linear constant-pressure wave that transports temperature and transverse momentum at the fluid velocity.
Vortex Shedding - Flow past Cylinder¶
This test case, based on [SHJ91], is an example of using an externally provided mesh from Gmsh. A cylinder with diameter \(D=1\) is centered at \((0,0)\) in a computational domain \(-4.5 \leq x \leq 15.5\), \(-4.5 \leq y \leq 4.5\). We solve this as a 3D problem with (default) one element in the \(z\) direction. The domain is filled with an ideal gas at rest (zero velocity) with temperature 24.92 and pressure 7143. The viscosity is 0.01 and thermal conductivity is 14.34 to maintain a Prandtl number of 0.71, which is typical for air. At time \(t=0\), this domain is subjected to freestream boundary conditions at the inflow (left) and Riemann-type outflow on the right, with exterior reference state at velocity \((1, 0, 0)\) giving Reynolds number \(100\) and Mach number \(0.01\). A symmetry (adiabatic free slip) condition is imposed at the top and bottom boundaries \((y = \pm 4.5)\) (zero normal velocity component, zero heat-flux). The cylinder wall is an adiabatic (no heat flux) no-slip boundary condition. As we evolve in time, eddies appear past the cylinder leading to a vortex shedding known as the vortex street, with shedding period of about 6.
The Gmsh input file, examples/meshes/cylinder.geo
is parametrized to facilitate experimenting with similar configurations.
The Strouhal number (nondimensional shedding frequency) is sensitive to the size of the computational domain and boundary conditions.
Forces on the cylinder walls are computed using the “reaction force” method, which is variationally consistent with the volume operator. Given the force components \(\bm F = (F_x, F_y, F_z)\) and surface area \(S = \pi D L_z\) where \(L_z\) is the spanwise extent of the domain, we define the coefficients of lift and drag as
where \(\rho_\infty, u_\infty\) are the freestream (inflow) density and velocity respectively.
Density Current¶
For this test problem (from [SWW+93]), we solve the full Navier-Stokes equations (1), for which a cold air bubble (of radius \(r_c\)) drops by convection in a neutrally stratified atmosphere. Its initial condition is defined in terms of the Exner pressure, \(\pi(\bm{x},t)\), and potential temperature, \(\theta(\bm{x},t)\), that relate to the state variables via
where \(P_0\) is the atmospheric pressure. For this problem, we have used no-slip and non-penetration boundary conditions for \(\bm{u}\), and no-flux for mass and energy densities.
Channel¶
A compressible channel flow. Analytical solution given in [Whi99]:
where \(H\) is the channel half-height, \(u_{\max}\) is the center velocity, \(T_w\) is the temperature at the wall, \(Pr=\frac{\mu}{c_p \kappa}\) is the Prandlt number, \(\hat E_c = \frac{u_{\max}^2}{c_p T_w}\) is the modified Eckert number, and \(Re_h = \frac{u_{\max}H}{\nu}\) is the Reynolds number.
Boundary conditions are periodic in the streamwise direction, and no-slip and non-penetration boundary conditions at the walls. The flow is driven by a body force determined analytically from the fluid properties and setup parameters \(H\) and \(u_{\max}\).
Flat Plate Boundary Layer¶
Laminar Boundary Layer - Blasius¶
Simulation of a laminar boundary layer flow, with the inflow being prescribed
by a Blasius similarity
solution. At the inflow,
the velocity is prescribed by the Blasius soution profile, density is set
constant, and temperature is allowed to float. Using weakT: true
, density is
allowed to float and temperature is set constant. At the outlet, a user-set
pressure is used for pressure in the inviscid flux terms (all other inviscid
flux terms use interior solution values). The wall is a no-slip,
no-penetration, no-heat flux condition. The top of the domain is treated as an
outflow and is tilted at a downward angle to ensure that flow is always exiting
it.
Turbulent Boundary Layer¶
Simulating a turbulent boundary layer without modeling the turbulence requires resolving the turbulent flow structures. These structures may be introduced into the simulations either by allowing a laminar boundary layer naturally transition to turbulence, or imposing turbulent structures at the inflow. The latter approach has been taken here, specifically using a synthetic turbulence generation (STG) method.
Synthetic Turbulence Generation (STG) Boundary Condition¶
We use the STG method described in [SSST14]. Below follows a re-description of the formulation to match the present notation, and then a description of the implementation and usage.
Equation Formulation¶
Here, we define the number of wavemodes \(N\), set of random numbers \( \{\bm{\sigma}^n, \bm{d}^n, \phi^n\}_{n=1}^N\), the Cholesky decomposition of the Reynolds stress tensor \(\bm{C}\) (such that \(\bm{R} = \bm{CC}^T\) ), bulk velocity \(U_0\), wavemode amplitude \(q^n\), wavemode frequency \(\kappa^n\), and \(\kappa_{\min} = 0.5 \min_{\bm{x}} (\kappa_e)\).
where \(l_t\) is the turbulence length scale, and \(d_w\) is the distance to the nearest wall.
The set of wavemode frequencies is defined by a geometric distribution:
The wavemode amplitudes \(q^n\) are defined by a model energy spectrum \(E(\kappa)\):
\(\kappa_\eta\) represents turbulent dissipation frequency, and is given as \(2\pi (\nu^3/\varepsilon)^{-1/4}\) with \(\nu\) the kinematic viscosity and \(\varepsilon\) the turbulent dissipation. \(\kappa_\mathrm{cut}\) approximates the effective cutoff frequency of the mesh (viewing the mesh as a filter on solution over \(\Omega\)) and is given by:
The enforcement of the boundary condition is identical to the blasius inflow;
it weakly enforces velocity, with the option of weakly enforcing either density
or temperature using the the -weakT
flag.
Initialization Data Flow¶
Data flow for initializing function (which creates the context data struct) is given below:
flowchart LR subgraph STGInflow.dat y lt[l_t] eps Rij[R_ij] ubar end subgraph STGRand.dat rand[RN Set]; end subgraph User Input u0[U0]; end subgraph init[Create Context Function] ke[k_e] N; end lt --Calc-->ke --Calc-->kn y --Calc-->ke subgraph context[Context Data] yC[y] randC[RN Set] Cij[C_ij] u0 --Copy--> u0C[U0] kn[k^n]; ubarC[ubar] ltC[l_t] epsC[eps] end ubar --Copy--> ubarC; y --Copy--> yC; lt --Copy--> ltC; eps --Copy--> epsC; rand --Copy--> randC; rand --> N --Calc--> kn; Rij --Calc--> Cij[C_ij]
This is done once at runtime. The spatially-varying terms are then evaluated at each quadrature point on-the-fly, either by interpolation (for \(l_t\), \(\varepsilon\), \(C_{ij}\), and \(\overline{\bm u}\)) or by calculation (for \(q^n\)).
The STGInflow.dat
file is a table of values at given distances from the wall.
These values are then interpolated to a physical location (node or quadrature
point). It has the following format:
[Total number of locations] 14
[d_w] [u_1] [u_2] [u_3] [R_11] [R_22] [R_33] [R_12] [R_13] [R_23] [sclr_1] [sclr_2] [l_t] [eps]
where each [ ]
item is a number in scientific notation (ie. 3.1415E0
), and sclr_1
and
sclr_2
are reserved for turbulence modeling variables. They are not used in
this example.
The STGRand.dat
file is the table of the random number set, \(\{\bm{\sigma}^n,
\bm{d}^n, \phi^n\}_{n=1}^N\). It has the format:
[Number of wavemodes] 7
[d_1] [d_2] [d_3] [phi] [sigma_1] [sigma_2] [sigma_3]
The following table is presented to help clarify the dimensionality of the numerous terms in the STG formulation.
Math |
Label |
\(f(\bm{x})\)? |
\(f(n)\)? |
---|---|---|---|
\( \{\bm{\sigma}^n, \bm{d}^n, \phi^n\}_{n=1}^N\) |
RN Set |
No |
Yes |
\(\bm{\overline{u}}\) |
ubar |
Yes |
No |
\(U_0\) |
U0 |
No |
No |
\(l_t\) |
l_t |
Yes |
No |
\(\varepsilon\) |
eps |
Yes |
No |
\(\bm{R}\) |
R_ij |
Yes |
No |
\(\bm{C}\) |
C_ij |
Yes |
No |
\(q^n\) |
q^n |
Yes |
Yes |
\(\{\kappa^n\}_{n=1}^N\) |
k^n |
No |
Yes |
\(h_i\) |
h_i |
Yes |
No |
\(d_w\) |
d_w |
Yes |
No |
Internal Damping Layer (IDL)¶
The STG inflow boundary condition creates large amplitude acoustic waves. We use an internal damping layer (IDL) to damp them out without disrupting the synthetic structures developing into natural turbulent structures. This implementation was inspired by [SSST14], but is implemented here as a ramped volumetric forcing term, similar to a sponge layer (see 8.4.2.4 in [Col23] for example). It takes the following form:
where \(\bm{Y}' = [P - P_\mathrm{ref}, \bm{0}, 0]^T\), and \(\sigma(\bm{x})\) is a linear ramp starting at -idl_start
with length -idl_length
and an amplitude of inverse -idl_decay_rate
.
The damping is defined in terms of a pressure-primitive anomaly \(\bm Y'\) converted to conservative source using \(\partial \bm{q}/\partial \bm{Y}\rvert_{\bm{q}}\), which is linearized about the current flow state.
\(P_\mathrm{ref}\) has a default value equal to -reference_pressure
flag, with an optional flag -idl_pressure
to set it to a different value.
Meshing¶
The flat plate boundary layer example has custom meshing features to better resolve the flow when using a generated box mesh.
These meshing features modify the nodal layout of the default, equispaced box mesh and are enabled via -mesh_transform platemesh
.
One of those is tilting the top of the domain, allowing for it to be a outflow boundary condition.
The angle of this tilt is controlled by -platemesh_top_angle
.
The primary meshing feature is the ability to grade the mesh, providing better
resolution near the wall. There are two methods to do this; algorithmically, or
specifying the node locations via a file. Algorithmically, a base node
distribution is defined at the inlet (assumed to be \(\min(x)\)) and then
linearly stretched/squeezed to match the slanted top boundary condition. Nodes
are placed such that -platemesh_Ndelta
elements are within
-platemesh_refine_height
of the wall. They are placed such that the element
height matches a geometric growth ratio defined by -platemesh_growth
. The
remaining elements are then distributed from -platemesh_refine_height
to the
top of the domain linearly in logarithmic space.
Alternatively, a file may be specified containing the locations of each node.
The file should be newline delimited, with the first line specifying the number
of points and the rest being the locations of the nodes. The node locations
used exactly at the inlet (assumed to be \(\min(x)\)) and linearly
stretched/squeezed to match the slanted top boundary condition. The file is
specified via -platemesh_y_node_locs_path
. If this flag is given an empty
string, then the algorithmic approach will be performed.
Taylor-Green Vortex¶
This problem is really just an initial condition, the Taylor-Green Vortex:
where \(\hat x = 2 \pi x / L\) for \(L\) the length of the domain in that specific direction. This coordinate modification is done to transform a given grid onto a domain of \(x,y,z \in [0, 2\pi)\).
This initial condition is traditionally given for the incompressible Navier-Stokes equations.
The reference state is selected using the -reference_{velocity,pressure,temperature}
flags (Euclidean norm of -reference_velocity
is used for \(V_0\)).