-
Notifications
You must be signed in to change notification settings - Fork 28
Double Mach Reflection
In this tutorial, the setup of an unsteady, inviscid, single-species simulation in a two-dimensional domain is demonstrated. The following capabilities of HAMeRS will be shown:
- Sixth-order shock capturing method WCNS6-LD
- Multiple levels of adaptive mesh refinement using Jameson sensor on density field to identify regions for refinement
- User-defined special boundary conditions
This is a non-dimensional single-species benchmark problem suggested by Woodward and Colella. The initial conditions of the problem is:
The ratio of specific heats is 1.4. The problem has a size of [0, 4] x [0, 1]. A Mach 10 shock initially makes a 60° angle with the horizontal wall at location x = 1/6 of the bottom boundary. As the shock moves and reflects on the wall, a complex shock structure with two triple points and a slip line evolves. The same initial and boundary conditions as Woodward and Colella are used. Ahead of the shock is undisturbed stationary air of with density of 1.4 and pressure of 1.0. At the bottom boundary, the conditions in the region x ∈ [0, 1/6] are fixed at the post-shock flow conditions and reflecting boundary conditions are used for x ≥ 1/6. The left boundary is set at the post-shock flow conditions and zero-gradient conditions are applied at the right boundary. Time-dependent conditions are applied on the top boundary to match the movement of the shock wave.
The file containing the initial conditions of this problem (DoubleMachReflection2D.cpp
) can be found in problems/Euler/initial_conditions
and the initial conditions should be set up by ln -sf <absolute path to DoubleMachReflection2D.cpp> src/apps/Euler/EulerInitialConditions.cpp
. The file containing the special boundary conditions of this problem (DoubleMachReflection2D.cpp
) can be found in problems/Euler/boundary_conditions
and the special boundary conditions should be set up by ln -sf <absolute path to DoubleMachReflection2D.cpp> src/apps/Euler/EulerSpecialBoundaryConditions.cpp
. The code has to be re-compiled after the links to the actual initial condition and special boundary condition files are set.
The configurations of the input file are discussed in this section. Only settings of several important blocks are discussed. The first thing to choose in the input file is whether it is an Euler (inviscid) or Navier-Stokes (diffusive and viscous) application. Since our problem is inviscid, we first set the application type to be Euler:
Application = "Euler"
The next thing to set is the block Euler
:
Euler
{
// Name of project
project_name = "2D double-Mach reflection"
// Number of species
num_species = 1
// Flow model to use
flow_model = "SINGLE_SPECIES"
Flow_model
{
// Equation of state to use
equation_of_state = "IDEAL_GAS"
Equation_of_state_mixing_rules
{
species_gamma = 1.4
species_R = 1.0
}
}
// Convective flux reconstructor to use
convective_flux_reconstructor = "WCNS6_LD_HLLC_HLL"
Convective_flux_reconstructor{}
Boundary_data
{
// Set the boundary conditions for edges
boundary_edge_xlo
{
boundary_condition = "DIRICHLET"
density = 8.0
velocity = 7.144709581, -4.125
pressure = 116.5
}
boundary_edge_xhi
{
boundary_condition = "FLOW"
}
boundary_edge_ylo
{
boundary_condition = "REFLECT"
}
boundary_edge_yhi
{
boundary_condition = "REFLECT"
}
// Set the boundary conditions for nodes
boundary_node_xlo_ylo
{
boundary_condition = "XDIRICHLET"
density = 8.0
velocity = 7.144709581, -4.125
pressure = 116.5
}
boundary_node_xhi_ylo
{
boundary_condition = "XFLOW"
}
boundary_node_xlo_yhi
{
boundary_condition = "XDIRICHLET"
density = 8.0
velocity = 7.144709581, -4.125
pressure = 116.5
}
boundary_node_xhi_yhi
{
boundary_condition = "XFLOW"
}
}
Gradient_tagger
{
gradient_sensors = "JAMESON_GRADIENT"
JAMESON_GRADIENT
{
Jameson_gradient_variables = "DENSITY"
Jameson_gradient_tol = 2.0e-2
}
}
}
Dirichlet boundary conditions are specified for the left boundary. The values of the primitive variables at the left boundary are set. Constant extrapolation is used for ghost cells at the right boundary. The boundary conditions of the lower and upper boundaries are set to "REFLECT"
arbitrarily since the actual boundary conditions are replaced by the special boundary conditions.
The settings for Main
is very similar to those of tutorial 1 and are not discussed.
The following settings are used for CartesianGeometry
:
CartesianGeometry
{
// Lower and upper indices of computational domain
domain_boxes = [(0, 0), (239, 59)]
x_lo = 0.0, 0.0 // Lower end of computational domain
x_up = 4.0, 1.0 // Upper end of computational domain
// Periodic dimension. A non-zero value indicates that the direction is periodic
periodic_dimension = 0, 0
}
The following settings are used for ExtendedTagAndInitialize
:
ExtendedTagAndInitialize
{
// Tagging method for refinement to use
tagging_method = "GRADIENT_DETECTOR"
}
The parameters of adaptive mesh refinement are set in PatchHierarchy
. In this tutorial, the maximum number of mesh levels is set to 3 and all levels have the same refinement ratio to coarser levels.
PatchHierarchy
{
// Maximum number of levels in hierarchy
max_levels = 3
ratio_to_coarser
{
// Vector ratio to next coarser level
level_1 = 2, 2 // all finer levels will use same values as level_1...
}
largest_patch_size
{
level_0 = 1000, 1000 // all finer levels will use same values as level_0...
}
smallest_patch_size
{
level_0 = 4, 4 // all finer levels will use same values as level_0...
}
}
The following settings are used for RungeKuttaLevelIntegrator
and TimeRefinementIntegrator
:
RungeKuttaLevelIntegrator
{
cfl = 0.4e0 // Max cfl factor used in problem
cfl_init = 0.4e0 // Initial cfl factor
lag_dt_computation = FALSE
use_ghosts_to_compute_dt = TRUE
}
TimeRefinementIntegrator
{
start_time = 0.0e0 // Initial simulation time
end_time = 2.0e-1 // Final simulation time
grow_dt = 1.0e0 // Growth factor for timesteps
max_integrator_steps = 10000 // Max number of simulation timesteps
tag_buffer = 2, 2 // array of integer values (one for each level that
// may be refined representing the number of cells
// by which tagged cells are buffered)
}
The tag_buffer
inside TimeRefinementIntegrator
represents the number of cells by which tagged cells are buffered before clustering into boxes.
To run the simulation with one core, first put the input file inside a directory named tutorial_04
under HAMeRS
. Then, execute the built main
executable inside build/src/exec/main
with the input file:
../build/exec/main <input filename>
To run the simulation with multiple cores, you can try mpirun/mpiexec/srun
, depending on the MPI library used for the compilation of HAMeRS. For example, if mpirun
is used:
mpirun -np <number of processors> ../build/src/exec/main <input filename>
The data can be visualized by opening dumps.visit
inside the viz folder with VisIt.The figure below shows the density field and refined regions at the end of simulation generated from VisIt. The black and red boxes show the second and third levels of meshes respectively:
- User Guide
- Programmer Guide
- Tutorials