|
| 1 | +using Trixi |
| 2 | + |
| 3 | +using OrdinaryDiffEqSDIRK |
| 4 | +using LinearSolve # For Jacobian-free Newton-Krylov (GMRES) solver |
| 5 | +using ADTypes # For automatic differentiation via finite differences |
| 6 | + |
| 7 | +# This is the classic 1D viscous shock wave problem with analytical solution |
| 8 | +# for a special value of the Prandtl number. |
| 9 | +# The original references are: |
| 10 | +# |
| 11 | +# - R. Becker (1922) |
| 12 | +# Stoßwelle und Detonation. |
| 13 | +# [DOI: 10.1007/BF01329605](https://doi.org/10.1007/BF01329605) |
| 14 | +# |
| 15 | +# English translations: |
| 16 | +# Impact waves and detonation. Part I. |
| 17 | +# https://ntrs.nasa.gov/api/citations/19930090862/downloads/19930090862.pdf |
| 18 | +# Impact waves and detonation. Part II. |
| 19 | +# https://ntrs.nasa.gov/api/citations/19930090863/downloads/19930090863.pdf |
| 20 | +# |
| 21 | +# - M. Morduchow, P. A. Libby (1949) |
| 22 | +# On a Complete Solution of the One-Dimensional Flow Equations |
| 23 | +# of a Viscous, Head-Conducting, Compressible Gas |
| 24 | +# [DOI: 10.2514/8.11882](https://doi.org/10.2514/8.11882) |
| 25 | +# |
| 26 | +# |
| 27 | +# The particular problem considered here is described in |
| 28 | +# - L. G. Margolin, J. M. Reisner, P. M. Jordan (2017) |
| 29 | +# Entropy in self-similar shock profiles |
| 30 | +# [DOI: 10.1016/j.ijnonlinmec.2017.07.003](https://doi.org/10.1016/j.ijnonlinmec.2017.07.003) |
| 31 | + |
| 32 | +### Fixed parameters ### |
| 33 | + |
| 34 | +# Special value for which nonlinear solver can be omitted |
| 35 | +# Corresponds essentially to fixing the Mach number |
| 36 | +alpha = 0.5 |
| 37 | +# We want kappa = cp * mu = mu_bar to ensure constant enthalpy |
| 38 | +prandtl_number() = 3 / 4 |
| 39 | + |
| 40 | +### Free choices: ### |
| 41 | +gamma() = 5 / 3 |
| 42 | + |
| 43 | +# In Margolin et al., the Navier-Stokes equations are given for an |
| 44 | +# isotropic stress tensor τ, i.e., ∇ ⋅ τ = μ Δu |
| 45 | +mu_isotropic() = 0.15 |
| 46 | +mu_bar() = mu_isotropic() / (gamma() - 1) # Re-scaled viscosity |
| 47 | + |
| 48 | +rho_0() = 1 |
| 49 | +v() = 1 # Shock speed |
| 50 | + |
| 51 | +domain_length = 4.0 |
| 52 | + |
| 53 | +### Derived quantities ### |
| 54 | + |
| 55 | +Ma() = 2 / sqrt(3 - gamma()) # Mach number for alpha = 0.5 |
| 56 | +c_0() = v() / Ma() # Speed of sound ahead of the shock |
| 57 | + |
| 58 | +# From constant enthalpy condition |
| 59 | +p_0() = c_0()^2 * rho_0() / gamma() |
| 60 | + |
| 61 | +l() = mu_bar() / (rho_0() * v()) * 2 * gamma() / (gamma() + 1) # Appropriate length scale |
| 62 | + |
| 63 | +""" |
| 64 | + initial_condition_viscous_shock(x, t, equations) |
| 65 | +
|
| 66 | +Classic 1D viscous shock wave problem with analytical solution |
| 67 | +for a special value of the Prandtl number. |
| 68 | +The version implemented here is described in |
| 69 | +- L. G. Margolin, J. M. Reisner, P. M. Jordan (2017) |
| 70 | + Entropy in self-similar shock profiles |
| 71 | + [DOI: 10.1016/j.ijnonlinmec.2017.07.003](https://doi.org/10.1016/j.ijnonlinmec.2017.07.003) |
| 72 | +""" |
| 73 | +function initial_condition_viscous_shock(x, t, equations) |
| 74 | + y = x[1] - v() * t # Translated coordinate |
| 75 | + |
| 76 | + # Coordinate transformation. See eq. (33) in Margolin et al. (2017) |
| 77 | + chi = 2 * exp(y / (2 * l())) |
| 78 | + |
| 79 | + w = 1 + 1 / (2 * chi^2) * (1 - sqrt(1 + 2 * chi^2)) |
| 80 | + |
| 81 | + rho = rho_0() / w |
| 82 | + u = v() * (1 - w) |
| 83 | + p = p_0() * 1 / w * (1 + (gamma() - 1) / 2 * Ma()^2 * (1 - w^2)) |
| 84 | + |
| 85 | + return prim2cons(SVector(rho, u, 0, p), equations) |
| 86 | +end |
| 87 | +initial_condition = initial_condition_viscous_shock |
| 88 | + |
| 89 | +############################################################################### |
| 90 | +# semidiscretization of the ideal compressible Navier-Stokes equations |
| 91 | + |
| 92 | +equations = CompressibleEulerEquations2D(gamma()) |
| 93 | + |
| 94 | +# Trixi implements the stress tensor in deviatoric form, thus we need to |
| 95 | +# convert the "isotropic viscosity" to the "deviatoric viscosity" |
| 96 | +mu_deviatoric() = mu_bar() * 3 / 4 |
| 97 | +equations_parabolic = CompressibleNavierStokesDiffusion2D(equations, mu = mu_deviatoric(), |
| 98 | + Prandtl = prandtl_number(), |
| 99 | + gradient_variables = GradientVariablesEntropy()) |
| 100 | + |
| 101 | +solver = DGSEM(polydeg = 3, surface_flux = flux_hlle) |
| 102 | + |
| 103 | +coordinates_min = (-domain_length / 2, -domain_length / 2) |
| 104 | +coordinates_max = (domain_length / 2, domain_length / 2) |
| 105 | + |
| 106 | +trees_per_dimension = (12, 3) |
| 107 | +mesh = P4estMesh(trees_per_dimension, |
| 108 | + polydeg = 3, initial_refinement_level = 0, |
| 109 | + coordinates_min = coordinates_min, coordinates_max = coordinates_max, |
| 110 | + periodicity = (false, true)) |
| 111 | + |
| 112 | +### Inviscid boundary conditions ### |
| 113 | + |
| 114 | +# Prescribe pure influx based on initial conditions |
| 115 | +function boundary_condition_inflow(u_inner, normal_direction::AbstractVector, x, t, |
| 116 | + surface_flux_function, |
| 117 | + equations::CompressibleEulerEquations2D) |
| 118 | + u_cons = initial_condition_viscous_shock(x, t, equations) |
| 119 | + flux = Trixi.flux(u_cons, normal_direction, equations) |
| 120 | + |
| 121 | + return flux |
| 122 | +end |
| 123 | + |
| 124 | +boundary_conditions = Dict(:x_neg => boundary_condition_inflow, |
| 125 | + :x_pos => boundary_condition_do_nothing) |
| 126 | + |
| 127 | +### Viscous boundary conditions ### |
| 128 | +# For the viscous BCs, we use the known analytical solution |
| 129 | +velocity_bc = NoSlip() do x, t, equations_parabolic |
| 130 | + Trixi.velocity(initial_condition_viscous_shock(x, |
| 131 | + t, |
| 132 | + equations_parabolic), |
| 133 | + equations_parabolic) |
| 134 | +end |
| 135 | + |
| 136 | +heat_bc = Isothermal() do x, t, equations_parabolic |
| 137 | + Trixi.temperature(initial_condition_viscous_shock(x, |
| 138 | + t, |
| 139 | + equations_parabolic), |
| 140 | + equations_parabolic) |
| 141 | +end |
| 142 | + |
| 143 | +boundary_condition_parabolic = BoundaryConditionNavierStokesWall(velocity_bc, heat_bc) |
| 144 | + |
| 145 | +boundary_conditions_parabolic = Dict(:x_neg => boundary_condition_parabolic, |
| 146 | + :x_pos => boundary_condition_parabolic) |
| 147 | + |
| 148 | +semi = SemidiscretizationHyperbolicParabolic(mesh, (equations, equations_parabolic), |
| 149 | + initial_condition, solver; |
| 150 | + boundary_conditions = (boundary_conditions, |
| 151 | + boundary_conditions_parabolic)) |
| 152 | + |
| 153 | +############################################################################### |
| 154 | +# ODE solvers, callbacks etc. |
| 155 | + |
| 156 | +tspan = (0.0, 1.0) |
| 157 | +ode = semidiscretize(semi, tspan) |
| 158 | + |
| 159 | +summary_callback = SummaryCallback() |
| 160 | +alive_callback = AliveCallback(alive_interval = 1) |
| 161 | +analysis_callback = AnalysisCallback(semi, interval = 100) |
| 162 | + |
| 163 | +callbacks = CallbackSet(summary_callback, alive_callback, analysis_callback) |
| 164 | + |
| 165 | +############################################################################### |
| 166 | +# run the simulation |
| 167 | + |
| 168 | +# Tolerances for GMRES residual, see https://jso.dev/Krylov.jl/stable/solvers/unsymmetric/#Krylov.gmres |
| 169 | +atol_lin_solve = 1e-5 |
| 170 | +rtol_lin_solve = 1e-5 |
| 171 | + |
| 172 | +# Jacobian-free Newton-Krylov (GMRES) solver |
| 173 | +linsolve = KrylovJL_GMRES(atol = atol_lin_solve, rtol = rtol_lin_solve) |
| 174 | + |
| 175 | +# Use (diagonally) implicit Runge-Kutta, see |
| 176 | +# https://docs.sciml.ai/DiffEqDocs/stable/tutorials/advanced_ode_example/#Using-Jacobian-Free-Newton-Krylov |
| 177 | +ode_alg = Kvaerno4(autodiff = AutoFiniteDiff(), linsolve = linsolve) |
| 178 | + |
| 179 | +atol_ode_solve = 1e-4 |
| 180 | +rtol_ode_solve = 1e-4 |
| 181 | +sol = solve(ode, ode_alg; |
| 182 | + abstol = atol_ode_solve, reltol = rtol_ode_solve, |
| 183 | + ode_default_options()..., callback = callbacks); |
0 commit comments