Path: blob/main/examples/dgmulti_3d/elixir_navierstokes_convergence_curved.jl
2055 views
using OrdinaryDiffEqLowStorageRK1using Trixi23###############################################################################4# semidiscretization of the ideal compressible Navier-Stokes equations56prandtl_number() = 0.727mu() = 0.0189equations = CompressibleEulerEquations3D(1.4)10equations_parabolic = CompressibleNavierStokesDiffusion3D(equations, mu = mu(),11Prandtl = prandtl_number(),12gradient_variables = GradientVariablesPrimitive())1314# Create DG solver with polynomial degree = 3 and (local) Lax-Friedrichs/Rusanov flux as surface flux1516# Up to version 0.13.0, `max_abs_speed_naive` was used as the default wave speed estimate of17# `const flux_lax_friedrichs = FluxLaxFriedrichs(), i.e., `FluxLaxFriedrichs(max_abs_speed = max_abs_speed_naive)`.18# In the `StepsizeCallback`, though, the less diffusive `max_abs_speeds` is employed which is consistent with `max_abs_speed`.19# Thus, we exchanged in PR#2458 the default wave speed used in the LLF flux to `max_abs_speed`.20# To ensure that every example still runs we specify explicitly `FluxLaxFriedrichs(max_abs_speed_naive)`.21# We remark, however, that the now default `max_abs_speed` is in general recommended due to compliance with the22# `StepsizeCallback` (CFL-Condition) and less diffusion.23dg = DGMulti(polydeg = 3, element_type = Hex(), approximation_type = Polynomial(),24surface_integral = SurfaceIntegralWeakForm(FluxLaxFriedrichs(max_abs_speed_naive)),25volume_integral = VolumeIntegralWeakForm())2627top_bottom(x, tol = 50 * eps()) = abs(abs(x[2]) - 1) < tol28is_on_boundary = Dict(:top_bottom => top_bottom)2930function mapping(xi, eta, zeta)31x = xi + 0.1 * sin(pi * xi) * sin(pi * eta)32y = eta + 0.1 * sin(pi * xi) * sin(pi * eta)33z = zeta + 0.1 * sin(pi * xi) * sin(pi * eta)34return SVector(x, y, z)35end36cells_per_dimension = (8, 8, 8)37mesh = DGMultiMesh(dg, cells_per_dimension, mapping; periodicity = (true, false, true),38is_on_boundary)3940# This initial condition is taken from `examples/dgmulti_3d/elixir_navierstokes_convergence.jl`4142# Note: the initial condition cannot be specialized to `CompressibleNavierStokesDiffusion3D`43# since it is called by both the parabolic solver (which passes in `CompressibleNavierStokesDiffusion3D`)44# and by the initial condition (which passes in `CompressibleEulerEquations3D`).45# This convergence test setup was originally derived by Andrew Winters (@andrewwinters5000)46function initial_condition_navier_stokes_convergence_test(x, t, equations)47# Constants. OBS! Must match those in `source_terms_navier_stokes_convergence_test`48c = 2.049A1 = 0.550A2 = 1.051A3 = 0.55253# Convenience values for trig. functions54pi_x = pi * x[1]55pi_y = pi * x[2]56pi_z = pi * x[3]57pi_t = pi * t5859rho = c + A1 * sin(pi_x) * cos(pi_y) * sin(pi_z) * cos(pi_t)60v1 = A2 * sin(pi_x) * log(x[2] + 2.0) * (1.0 - exp(-A3 * (x[2] - 1.0))) * sin(pi_z) *61cos(pi_t)62v2 = v163v3 = v164p = rho^26566return prim2cons(SVector(rho, v1, v2, v3, p), equations)67end6869@inline function source_terms_navier_stokes_convergence_test(u, x, t, equations)70# TODO: parabolic71# we currently need to hardcode these parameters until we fix the "combined equation" issue72# see also https://github.com/trixi-framework/Trixi.jl/pull/116073inv_gamma_minus_one = inv(equations.gamma - 1)74Pr = prandtl_number()75mu_ = mu()7677# Constants. OBS! Must match those in `initial_condition_navier_stokes_convergence_test`78c = 2.079A1 = 0.580A2 = 1.081A3 = 0.58283# Convenience values for trig. functions84pi_x = pi * x[1]85pi_y = pi * x[2]86pi_z = pi * x[3]87pi_t = pi * t8889# Define auxiliary functions for the strange function of the y variable90# to make expressions easier to read91g = log(x[2] + 2.0) * (1.0 - exp(-A3 * (x[2] - 1.0)))92g_y = (A3 * log(x[2] + 2.0) * exp(-A3 * (x[2] - 1.0)) +93(1.0 - exp(-A3 * (x[2] - 1.0))) / (x[2] + 2.0))94g_yy = (2.0 * A3 * exp(-A3 * (x[2] - 1.0)) / (x[2] + 2.0) -95(1.0 - exp(-A3 * (x[2] - 1.0))) / ((x[2] + 2.0)^2) -96A3^2 * log(x[2] + 2.0) * exp(-A3 * (x[2] - 1.0)))9798# Density and its derivatives99rho = c + A1 * sin(pi_x) * cos(pi_y) * sin(pi_z) * cos(pi_t)100rho_t = -pi * A1 * sin(pi_x) * cos(pi_y) * sin(pi_z) * sin(pi_t)101rho_x = pi * A1 * cos(pi_x) * cos(pi_y) * sin(pi_z) * cos(pi_t)102rho_y = -pi * A1 * sin(pi_x) * sin(pi_y) * sin(pi_z) * cos(pi_t)103rho_z = pi * A1 * sin(pi_x) * cos(pi_y) * cos(pi_z) * cos(pi_t)104rho_xx = -pi^2 * (rho - c)105rho_yy = -pi^2 * (rho - c)106rho_zz = -pi^2 * (rho - c)107108# Velocities and their derivatives109# v1 terms110v1 = A2 * sin(pi_x) * g * sin(pi_z) * cos(pi_t)111v1_t = -pi * A2 * sin(pi_x) * g * sin(pi_z) * sin(pi_t)112v1_x = pi * A2 * cos(pi_x) * g * sin(pi_z) * cos(pi_t)113v1_y = A2 * sin(pi_x) * g_y * sin(pi_z) * cos(pi_t)114v1_z = pi * A2 * sin(pi_x) * g * cos(pi_z) * cos(pi_t)115v1_xx = -pi^2 * v1116v1_yy = A2 * sin(pi_x) * g_yy * sin(pi_z) * cos(pi_t)117v1_zz = -pi^2 * v1118v1_xy = pi * A2 * cos(pi_x) * g_y * sin(pi_z) * cos(pi_t)119v1_xz = pi^2 * A2 * cos(pi_x) * g * cos(pi_z) * cos(pi_t)120v1_yz = pi * A2 * sin(pi_x) * g_y * cos(pi_z) * cos(pi_t)121# v2 terms (simplifies from ansatz)122v2 = v1123v2_t = v1_t124v2_x = v1_x125v2_y = v1_y126v2_z = v1_z127v2_xx = v1_xx128v2_yy = v1_yy129v2_zz = v1_zz130v2_xy = v1_xy131v2_yz = v1_yz132# v3 terms (simplifies from ansatz)133v3 = v1134v3_t = v1_t135v3_x = v1_x136v3_y = v1_y137v3_z = v1_z138v3_xx = v1_xx139v3_yy = v1_yy140v3_zz = v1_zz141v3_xz = v1_xz142v3_yz = v1_yz143144# Pressure and its derivatives145p = rho^2146p_t = 2.0 * rho * rho_t147p_x = 2.0 * rho * rho_x148p_y = 2.0 * rho * rho_y149p_z = 2.0 * rho * rho_z150151# Total energy and its derivatives; simiplifies from ansatz that v2 = v1 and v3 = v1152E = p * inv_gamma_minus_one + 1.5 * rho * v1^2153E_t = p_t * inv_gamma_minus_one + 1.5 * rho_t * v1^2 + 3.0 * rho * v1 * v1_t154E_x = p_x * inv_gamma_minus_one + 1.5 * rho_x * v1^2 + 3.0 * rho * v1 * v1_x155E_y = p_y * inv_gamma_minus_one + 1.5 * rho_y * v1^2 + 3.0 * rho * v1 * v1_y156E_z = p_z * inv_gamma_minus_one + 1.5 * rho_z * v1^2 + 3.0 * rho * v1 * v1_z157158# Divergence of Fick's law ∇⋅∇q = kappa ∇⋅∇T; simplifies because p = rho², so T = p/rho = rho159kappa = equations.gamma * inv_gamma_minus_one / Pr160q_xx = kappa * rho_xx # kappa T_xx161q_yy = kappa * rho_yy # kappa T_yy162q_zz = kappa * rho_zz # kappa T_zz163164# Stress tensor and its derivatives (exploit symmetry)165tau11 = 4.0 / 3.0 * v1_x - 2.0 / 3.0 * (v2_y + v3_z)166tau12 = v1_y + v2_x167tau13 = v1_z + v3_x168tau22 = 4.0 / 3.0 * v2_y - 2.0 / 3.0 * (v1_x + v3_z)169tau23 = v2_z + v3_y170tau33 = 4.0 / 3.0 * v3_z - 2.0 / 3.0 * (v1_x + v2_y)171172tau11_x = 4.0 / 3.0 * v1_xx - 2.0 / 3.0 * (v2_xy + v3_xz)173tau12_x = v1_xy + v2_xx174tau13_x = v1_xz + v3_xx175176tau12_y = v1_yy + v2_xy177tau22_y = 4.0 / 3.0 * v2_yy - 2.0 / 3.0 * (v1_xy + v3_yz)178tau23_y = v2_yz + v3_yy179180tau13_z = v1_zz + v3_xz181tau23_z = v2_zz + v3_yz182tau33_z = 4.0 / 3.0 * v3_zz - 2.0 / 3.0 * (v1_xz + v2_yz)183184# Compute the source terms185# Density equation186du1 = (rho_t + rho_x * v1 + rho * v1_x187+ rho_y * v2 + rho * v2_y188+ rho_z * v3 + rho * v3_z)189# x-momentum equation190du2 = (rho_t * v1 + rho * v1_t + p_x + rho_x * v1^2191+ 2.0 * rho * v1 * v1_x192+ rho_y * v1 * v2193+ rho * v1_y * v2194+ rho * v1 * v2_y195+ rho_z * v1 * v3196+ rho * v1_z * v3197+ rho * v1 * v3_z -198mu_ * (tau11_x + tau12_y + tau13_z))199# y-momentum equation200du3 = (rho_t * v2 + rho * v2_t + p_y + rho_x * v1 * v2201+ rho * v1_x * v2202+ rho * v1 * v2_x203+ rho_y * v2^2204+ 2.0 * rho * v2 * v2_y205+ rho_z * v2 * v3206+ rho * v2_z * v3207+ rho * v2 * v3_z -208mu_ * (tau12_x + tau22_y + tau23_z))209# z-momentum equation210du4 = (rho_t * v3 + rho * v3_t + p_z + rho_x * v1 * v3211+ rho * v1_x * v3212+ rho * v1 * v3_x213+ rho_y * v2 * v3214+ rho * v2_y * v3215+ rho * v2 * v3_y216+ rho_z * v3^2217+ 2.0 * rho * v3 * v3_z -218mu_ * (tau13_x + tau23_y + tau33_z))219# Total energy equation220du5 = (E_t + v1_x * (E + p) + v1 * (E_x + p_x)221+ v2_y * (E + p) + v2 * (E_y + p_y)222+ v3_z * (E + p) + v3 * (E_z + p_z) -223# stress tensor and temperature gradient from x-direction224mu_ * (q_xx + v1_x * tau11 + v2_x * tau12 + v3_x * tau13225+ v1 * tau11_x + v2 * tau12_x + v3 * tau13_x) -226# stress tensor and temperature gradient terms from y-direction227mu_ * (q_yy + v1_y * tau12 + v2_y * tau22 + v3_y * tau23228+ v1 * tau12_y + v2 * tau22_y + v3 * tau23_y) -229# stress tensor and temperature gradient terms from z-direction230mu_ * (q_zz + v1_z * tau13 + v2_z * tau23 + v3_z * tau33231+ v1 * tau13_z + v2 * tau23_z + v3 * tau33_z))232233return SVector(du1, du2, du3, du4, du5)234end235236initial_condition = initial_condition_navier_stokes_convergence_test237238# BC types239velocity_bc_top_bottom = NoSlip() do x, t, equations_parabolic240u_cons = initial_condition_navier_stokes_convergence_test(x, t, equations_parabolic)241return SVector(u_cons[2] / u_cons[1], u_cons[3] / u_cons[1], u_cons[4] / u_cons[1])242end243244heat_bc_top_bottom = Adiabatic((x, t, equations_parabolic) -> 0.0)245boundary_condition_top_bottom = BoundaryConditionNavierStokesWall(velocity_bc_top_bottom,246heat_bc_top_bottom)247248# define inviscid boundary conditions249boundary_conditions = (; :top_bottom => boundary_condition_slip_wall)250251# define viscous boundary conditions252boundary_conditions_parabolic = (; :top_bottom => boundary_condition_top_bottom)253254semi = SemidiscretizationHyperbolicParabolic(mesh, (equations, equations_parabolic),255initial_condition, dg;256boundary_conditions = (boundary_conditions,257boundary_conditions_parabolic),258source_terms = source_terms_navier_stokes_convergence_test)259260###############################################################################261# ODE solvers, callbacks etc.262263# Create ODE problem with time span `tspan`264tspan = (0.0, 1.0)265ode = semidiscretize(semi, tspan)266267summary_callback = SummaryCallback()268alive_callback = AliveCallback(alive_interval = 10)269analysis_interval = 100270analysis_callback = AnalysisCallback(semi, interval = analysis_interval, uEltype = real(dg))271save_solution = SaveSolutionCallback(interval = analysis_interval,272solution_variables = cons2prim)273callbacks = CallbackSet(summary_callback, alive_callback, analysis_callback, save_solution)274275###############################################################################276# run the simulation277278time_int_tol = 1e-8279sol = solve(ode, RDPK3SpFSAL49(); abstol = time_int_tol, reltol = time_int_tol,280ode_default_options()..., callback = callbacks)281282283