Path: blob/main/examples/dgmulti_2d/elixir_mhd_reflective_wall.jl
2055 views
using OrdinaryDiffEqLowStorageRK1using Trixi2using LinearAlgebra: norm, dot # for use in the MHD boundary condition34###############################################################################5# semidiscretization of the compressible ideal GLM-MHD equations6equations = IdealGlmMhdEquations2D(1.4)78function initial_condition_perturbation(x, t, equations::IdealGlmMhdEquations2D)9# pressure perturbation in a vertically magnetized field on the domain [-1, 1]^21011r2 = (x[1] + 0.25)^2 + (x[2] + 0.25)^21213rho = 1.014v1 = 0.015v2 = 0.016v3 = 0.017p = 1 + 0.5 * exp(-100 * r2)1819# the pressure and magnetic field are chosen to be strongly20# magnetized, such that p / ||B||^2 ≈ 0.01.21B1 = 0.022B2 = 40.0 / sqrt(4.0 * pi)23B3 = 0.02425psi = 0.026return prim2cons(SVector(rho, v1, v2, v3, p, B1, B2, B3, psi), equations)27end28initial_condition = initial_condition_perturbation2930# Up to version 0.13.0, `max_abs_speed_naive` was used as the default wave speed estimate of31# `const flux_lax_friedrichs = FluxLaxFriedrichs(), i.e., `FluxLaxFriedrichs(max_abs_speed = max_abs_speed_naive)`.32# In the `StepsizeCallback`, though, the less diffusive `max_abs_speeds` is employed which is consistent with `max_abs_speed`.33# Thus, we exchanged in PR#2458 the default wave speed used in the LLF flux to `max_abs_speed`.34# To ensure that every example still runs we specify explicitly `FluxLaxFriedrichs(max_abs_speed_naive)`.35# We remark, however, that the now default `max_abs_speed` is in general recommended due to compliance with the36# `StepsizeCallback` (CFL-Condition) and less diffusion.37surface_flux = (FluxLaxFriedrichs(max_abs_speed_naive), flux_nonconservative_powell)38volume_flux = (flux_hindenlang_gassner, flux_nonconservative_powell)3940solver = DGMulti(polydeg = 3, element_type = Quad(), approximation_type = GaussSBP(),41surface_integral = SurfaceIntegralWeakForm(surface_flux),42volume_integral = VolumeIntegralFluxDifferencing(volume_flux))4344x_neg(x, tol = 50 * eps()) = abs(x[1] + 1) < tol45x_pos(x, tol = 50 * eps()) = abs(x[1] - 1) < tol46y_neg(x, tol = 50 * eps()) = abs(x[2] + 1) < tol47y_pos(x, tol = 50 * eps()) = abs(x[2] - 1) < tol48is_on_boundary = Dict(:x_neg => x_neg, :x_pos => x_pos, :y_neg => y_neg, :y_pos => y_pos)4950cells_per_dimension = (16, 16)51mesh = DGMultiMesh(solver, cells_per_dimension; periodicity = (false, false),52is_on_boundary)5354# Create a "reflective-like" boundary condition by mirroring the velocity but leaving the magnetic field alone.55# Note that this boundary condition is probably not entropy stable.56function boundary_condition_velocity_slip_wall(u_inner, normal_direction::AbstractVector,57x, t, surface_flux_functions,58equations::IdealGlmMhdEquations2D)59surface_flux_function, nonconservative_flux_function = surface_flux_functions60# Normalize the vector without using `normalize` since we need to multiply by the `norm_` later61norm_ = norm(normal_direction)62normal = normal_direction / norm_6364# compute the primitive variables65rho, v1, v2, v3, p, B1, B2, B3, psi = cons2prim(u_inner, equations)6667v_normal = dot(normal, SVector(v1, v2))68u_mirror = prim2cons(SVector(rho, v1 - 2 * v_normal * normal[1],69v2 - 2 * v_normal * normal[2],70v3, p, B1, B2, B3, psi), equations)71flux = surface_flux_function(u_inner, u_mirror, normal, equations) * norm_72noncons_flux = nonconservative_flux_function(u_inner, u_mirror, normal, equations) *73norm_74return flux, noncons_flux75end7677boundary_conditions = (; x_neg = boundary_condition_velocity_slip_wall,78x_pos = boundary_condition_velocity_slip_wall,79y_neg = boundary_condition_do_nothing,80y_pos = BoundaryConditionDirichlet(initial_condition))8182semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver;83boundary_conditions = boundary_conditions)8485###############################################################################86# ODE solvers, callbacks etc.8788tspan = (0.0, 0.075)89ode = semidiscretize(semi, tspan)9091summary_callback = SummaryCallback()9293analysis_interval = 10094analysis_callback = AnalysisCallback(semi, interval = analysis_interval,95uEltype = real(solver))96alive_callback = AliveCallback(alive_interval = 10)9798cfl = 0.599stepsize_callback = StepsizeCallback(cfl = cfl)100glm_speed_callback = GlmSpeedCallback(glm_scale = 0.5, cfl = cfl)101102save_solution = SaveSolutionCallback(interval = analysis_interval,103solution_variables = cons2prim)104105callbacks = CallbackSet(summary_callback,106analysis_callback,107alive_callback,108stepsize_callback,109glm_speed_callback,110save_solution)111112###############################################################################113# run the simulation114115sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false);116dt = 1e-5, # solve needs some value here but it will be overwritten by the stepsize_callback117ode_default_options()..., callback = callbacks);118119120