Path: blob/main/examples/dgmulti_2d/elixir_navierstokes_convergence_curved.jl
2055 views
using OrdinaryDiffEqLowStorageRK1using Trixi23###############################################################################4# semidiscretization of the ideal compressible Navier-Stokes equations56prandtl_number() = 0.727mu() = 0.0189equations = CompressibleEulerEquations2D(1.4)10# Note: If you change the Navier-Stokes parameters here, also change them in the initial condition11# I really do not like this structure but it should work for now12equations_parabolic = CompressibleNavierStokesDiffusion2D(equations, mu = mu(),13Prandtl = prandtl_number(),14gradient_variables = GradientVariablesPrimitive())1516# Create DG solver with polynomial degree = 3 and (local) Lax-Friedrichs/Rusanov flux as surface flux1718# Up to version 0.13.0, `max_abs_speed_naive` was used as the default wave speed estimate of19# `const flux_lax_friedrichs = FluxLaxFriedrichs(), i.e., `FluxLaxFriedrichs(max_abs_speed = max_abs_speed_naive)`.20# In the `StepsizeCallback`, though, the less diffusive `max_abs_speeds` is employed which is consistent with `max_abs_speed`.21# Thus, we exchanged in PR#2458 the default wave speed used in the LLF flux to `max_abs_speed`.22# To ensure that every example still runs we specify explicitly `FluxLaxFriedrichs(max_abs_speed_naive)`.23# We remark, however, that the now default `max_abs_speed` is in general recommended due to compliance with the24# `StepsizeCallback` (CFL-Condition) and less diffusion.25dg = DGMulti(polydeg = 3, element_type = Tri(), approximation_type = Polynomial(),26surface_integral = SurfaceIntegralWeakForm(FluxLaxFriedrichs(max_abs_speed_naive)),27volume_integral = VolumeIntegralWeakForm())2829top_bottom(x, tol = 50 * eps()) = abs(abs(x[2]) - 1) < tol30is_on_boundary = Dict(:top_bottom => top_bottom)3132function mapping(xi, eta)33x = xi + 0.1 * sin(pi * xi) * sin(pi * eta)34y = eta + 0.1 * sin(pi * xi) * sin(pi * eta)35return SVector(x, y)36end37cells_per_dimension = (16, 16)38mesh = DGMultiMesh(dg, cells_per_dimension, mapping; periodicity = (true, false),39is_on_boundary)4041# This initial condition is taken from `examples/dgmulti_2d/elixir_navierstokes_convergence.jl`4243# Note: the initial condition cannot be specialized to `CompressibleNavierStokesDiffusion2D`44# since it is called by both the parabolic solver (which passes in `CompressibleNavierStokesDiffusion2D`)45# and by the initial condition (which passes in `CompressibleEulerEquations2D`).46# This convergence test setup was originally derived by Andrew Winters (@andrewwinters5000)47function initial_condition_navier_stokes_convergence_test(x, t, equations)48# Amplitude and shift49A = 0.550c = 2.05152# convenience values for trig. functions53pi_x = pi * x[1]54pi_y = pi * x[2]55pi_t = pi * t5657rho = c + A * sin(pi_x) * cos(pi_y) * cos(pi_t)58v1 = sin(pi_x) * log(x[2] + 2.0) * (1.0 - exp(-A * (x[2] - 1.0))) * cos(pi_t)59v2 = v160p = rho^26162return prim2cons(SVector(rho, v1, v2, p), equations)63end6465@inline function source_terms_navier_stokes_convergence_test(u, x, t, equations)66y = x[2]6768# TODO: parabolic69# we currently need to hardcode these parameters until we fix the "combined equation" issue70# see also https://github.com/trixi-framework/Trixi.jl/pull/116071inv_gamma_minus_one = inv(equations.gamma - 1)72Pr = prandtl_number()73mu_ = mu()7475# Same settings as in `initial_condition`76# Amplitude and shift77A = 0.578c = 2.07980# convenience values for trig. functions81pi_x = pi * x[1]82pi_y = pi * x[2]83pi_t = pi * t8485# compute the manufactured solution and all necessary derivatives86rho = c + A * sin(pi_x) * cos(pi_y) * cos(pi_t)87rho_t = -pi * A * sin(pi_x) * cos(pi_y) * sin(pi_t)88rho_x = pi * A * cos(pi_x) * cos(pi_y) * cos(pi_t)89rho_y = -pi * A * sin(pi_x) * sin(pi_y) * cos(pi_t)90rho_xx = -pi * pi * A * sin(pi_x) * cos(pi_y) * cos(pi_t)91rho_yy = -pi * pi * A * sin(pi_x) * cos(pi_y) * cos(pi_t)9293v1 = sin(pi_x) * log(y + 2.0) * (1.0 - exp(-A * (y - 1.0))) * cos(pi_t)94v1_t = -pi * sin(pi_x) * log(y + 2.0) * (1.0 - exp(-A * (y - 1.0))) * sin(pi_t)95v1_x = pi * cos(pi_x) * log(y + 2.0) * (1.0 - exp(-A * (y - 1.0))) * cos(pi_t)96v1_y = sin(pi_x) *97(A * log(y + 2.0) * exp(-A * (y - 1.0)) +98(1.0 - exp(-A * (y - 1.0))) / (y + 2.0)) * cos(pi_t)99v1_xx = -pi * pi * sin(pi_x) * log(y + 2.0) * (1.0 - exp(-A * (y - 1.0))) * cos(pi_t)100v1_xy = pi * cos(pi_x) *101(A * log(y + 2.0) * exp(-A * (y - 1.0)) +102(1.0 - exp(-A * (y - 1.0))) / (y + 2.0)) * cos(pi_t)103v1_yy = (sin(pi_x) *104(2.0 * A * exp(-A * (y - 1.0)) / (y + 2.0) -105A * A * log(y + 2.0) * exp(-A * (y - 1.0)) -106(1.0 - exp(-A * (y - 1.0))) / ((y + 2.0) * (y + 2.0))) * cos(pi_t))107v2 = v1108v2_t = v1_t109v2_x = v1_x110v2_y = v1_y111v2_xx = v1_xx112v2_xy = v1_xy113v2_yy = v1_yy114115p = rho * rho116p_t = 2.0 * rho * rho_t117p_x = 2.0 * rho * rho_x118p_y = 2.0 * rho * rho_y119p_xx = 2.0 * rho * rho_xx + 2.0 * rho_x * rho_x120p_yy = 2.0 * rho * rho_yy + 2.0 * rho_y * rho_y121122# Note this simplifies slightly because the ansatz assumes that v1 = v2123E = p * inv_gamma_minus_one + 0.5 * rho * (v1^2 + v2^2)124E_t = p_t * inv_gamma_minus_one + rho_t * v1^2 + 2.0 * rho * v1 * v1_t125E_x = p_x * inv_gamma_minus_one + rho_x * v1^2 + 2.0 * rho * v1 * v1_x126E_y = p_y * inv_gamma_minus_one + rho_y * v1^2 + 2.0 * rho * v1 * v1_y127128# Some convenience constants129T_const = equations.gamma * inv_gamma_minus_one / Pr130inv_rho_cubed = 1.0 / (rho^3)131132# compute the source terms133# density equation134du1 = rho_t + rho_x * v1 + rho * v1_x + rho_y * v2 + rho * v2_y135136# x-momentum equation137du2 = (rho_t * v1 + rho * v1_t + p_x + rho_x * v1^2138+ 2.0 * rho * v1 * v1_x139+ rho_y * v1 * v2140+ rho * v1_y * v2141+ rho * v1 * v2_y -142# stress tensor from x-direction1434.0 / 3.0 * v1_xx * mu_ +1442.0 / 3.0 * v2_xy * mu_ -145v1_yy * mu_ -146v2_xy * mu_)147# y-momentum equation148du3 = (rho_t * v2 + rho * v2_t + p_y + rho_x * v1 * v2149+ rho * v1_x * v2150+ rho * v1 * v2_x151+ rho_y * v2^2152+ 2.0 * rho * v2 * v2_y -153# stress tensor from y-direction154v1_xy * mu_ -155v2_xx * mu_ -1564.0 / 3.0 * v2_yy * mu_ +1572.0 / 3.0 * v1_xy * mu_)158# total energy equation159du4 = (E_t + v1_x * (E + p) + v1 * (E_x + p_x)160+ v2_y * (E + p) + v2 * (E_y + p_y) -161# stress tensor and temperature gradient terms from x-direction1624.0 / 3.0 * v1_xx * v1 * mu_ +1632.0 / 3.0 * v2_xy * v1 * mu_ -1644.0 / 3.0 * v1_x * v1_x * mu_ +1652.0 / 3.0 * v2_y * v1_x * mu_ -166v1_xy * v2 * mu_ -167v2_xx * v2 * mu_ -168v1_y * v2_x * mu_ -169v2_x * v2_x * mu_ -170T_const * inv_rho_cubed *171(p_xx * rho * rho -1722.0 * p_x * rho * rho_x +1732.0 * p * rho_x * rho_x -174p * rho * rho_xx) * mu_ -175# stress tensor and temperature gradient terms from y-direction176v1_yy * v1 * mu_ -177v2_xy * v1 * mu_ -178v1_y * v1_y * mu_ -179v2_x * v1_y * mu_ -1804.0 / 3.0 * v2_yy * v2 * mu_ +1812.0 / 3.0 * v1_xy * v2 * mu_ -1824.0 / 3.0 * v2_y * v2_y * mu_ +1832.0 / 3.0 * v1_x * v2_y * mu_ -184T_const * inv_rho_cubed *185(p_yy * rho * rho -1862.0 * p_y * rho * rho_y +1872.0 * p * rho_y * rho_y -188p * rho * rho_yy) * mu_)189190return SVector(du1, du2, du3, du4)191end192193initial_condition = initial_condition_navier_stokes_convergence_test194195# BC types196velocity_bc_top_bottom = NoSlip() do x, t, equations_parabolic197u_cons = initial_condition_navier_stokes_convergence_test(x, t, equations_parabolic)198return SVector(u_cons[2] / u_cons[1], u_cons[3] / u_cons[1])199end200201heat_bc_top_bottom = Adiabatic((x, t, equations_parabolic) -> 0.0)202boundary_condition_top_bottom = BoundaryConditionNavierStokesWall(velocity_bc_top_bottom,203heat_bc_top_bottom)204205# define inviscid boundary conditions206boundary_conditions = (; :top_bottom => boundary_condition_slip_wall)207208# define viscous boundary conditions209boundary_conditions_parabolic = (; :top_bottom => boundary_condition_top_bottom)210211semi = SemidiscretizationHyperbolicParabolic(mesh, (equations, equations_parabolic),212initial_condition, dg;213boundary_conditions = (boundary_conditions,214boundary_conditions_parabolic),215source_terms = source_terms_navier_stokes_convergence_test)216217###############################################################################218# ODE solvers, callbacks etc.219220# Create ODE problem with time span `tspan`221tspan = (0.0, 0.5)222ode = semidiscretize(semi, tspan)223224summary_callback = SummaryCallback()225alive_callback = AliveCallback(alive_interval = 10)226analysis_interval = 100227analysis_callback = AnalysisCallback(semi, interval = analysis_interval, uEltype = real(dg))228save_solution = SaveSolutionCallback(interval = analysis_interval,229solution_variables = cons2prim)230callbacks = CallbackSet(summary_callback, alive_callback, analysis_callback, save_solution)231232###############################################################################233# run the simulation234235time_int_tol = 1e-8236sol = solve(ode, RDPK3SpFSAL49(); abstol = time_int_tol, reltol = time_int_tol,237ode_default_options()..., callback = callbacks)238239240