Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
trixi-framework
GitHub Repository: trixi-framework/Trixi.jl
Path: blob/main/examples/dgmulti_2d/elixir_mhd_reflective_wall.jl
2055 views
1
using OrdinaryDiffEqLowStorageRK
2
using Trixi
3
using LinearAlgebra: norm, dot # for use in the MHD boundary condition
4
5
###############################################################################
6
# semidiscretization of the compressible ideal GLM-MHD equations
7
equations = IdealGlmMhdEquations2D(1.4)
8
9
function initial_condition_perturbation(x, t, equations::IdealGlmMhdEquations2D)
10
# pressure perturbation in a vertically magnetized field on the domain [-1, 1]^2
11
12
r2 = (x[1] + 0.25)^2 + (x[2] + 0.25)^2
13
14
rho = 1.0
15
v1 = 0.0
16
v2 = 0.0
17
v3 = 0.0
18
p = 1 + 0.5 * exp(-100 * r2)
19
20
# the pressure and magnetic field are chosen to be strongly
21
# magnetized, such that p / ||B||^2 ≈ 0.01.
22
B1 = 0.0
23
B2 = 40.0 / sqrt(4.0 * pi)
24
B3 = 0.0
25
26
psi = 0.0
27
return prim2cons(SVector(rho, v1, v2, v3, p, B1, B2, B3, psi), equations)
28
end
29
initial_condition = initial_condition_perturbation
30
31
# Up to version 0.13.0, `max_abs_speed_naive` was used as the default wave speed estimate of
32
# `const flux_lax_friedrichs = FluxLaxFriedrichs(), i.e., `FluxLaxFriedrichs(max_abs_speed = max_abs_speed_naive)`.
33
# In the `StepsizeCallback`, though, the less diffusive `max_abs_speeds` is employed which is consistent with `max_abs_speed`.
34
# Thus, we exchanged in PR#2458 the default wave speed used in the LLF flux to `max_abs_speed`.
35
# To ensure that every example still runs we specify explicitly `FluxLaxFriedrichs(max_abs_speed_naive)`.
36
# We remark, however, that the now default `max_abs_speed` is in general recommended due to compliance with the
37
# `StepsizeCallback` (CFL-Condition) and less diffusion.
38
surface_flux = (FluxLaxFriedrichs(max_abs_speed_naive), flux_nonconservative_powell)
39
volume_flux = (flux_hindenlang_gassner, flux_nonconservative_powell)
40
41
solver = DGMulti(polydeg = 3, element_type = Quad(), approximation_type = GaussSBP(),
42
surface_integral = SurfaceIntegralWeakForm(surface_flux),
43
volume_integral = VolumeIntegralFluxDifferencing(volume_flux))
44
45
x_neg(x, tol = 50 * eps()) = abs(x[1] + 1) < tol
46
x_pos(x, tol = 50 * eps()) = abs(x[1] - 1) < tol
47
y_neg(x, tol = 50 * eps()) = abs(x[2] + 1) < tol
48
y_pos(x, tol = 50 * eps()) = abs(x[2] - 1) < tol
49
is_on_boundary = Dict(:x_neg => x_neg, :x_pos => x_pos, :y_neg => y_neg, :y_pos => y_pos)
50
51
cells_per_dimension = (16, 16)
52
mesh = DGMultiMesh(solver, cells_per_dimension; periodicity = (false, false),
53
is_on_boundary)
54
55
# Create a "reflective-like" boundary condition by mirroring the velocity but leaving the magnetic field alone.
56
# Note that this boundary condition is probably not entropy stable.
57
function boundary_condition_velocity_slip_wall(u_inner, normal_direction::AbstractVector,
58
x, t, surface_flux_functions,
59
equations::IdealGlmMhdEquations2D)
60
surface_flux_function, nonconservative_flux_function = surface_flux_functions
61
# Normalize the vector without using `normalize` since we need to multiply by the `norm_` later
62
norm_ = norm(normal_direction)
63
normal = normal_direction / norm_
64
65
# compute the primitive variables
66
rho, v1, v2, v3, p, B1, B2, B3, psi = cons2prim(u_inner, equations)
67
68
v_normal = dot(normal, SVector(v1, v2))
69
u_mirror = prim2cons(SVector(rho, v1 - 2 * v_normal * normal[1],
70
v2 - 2 * v_normal * normal[2],
71
v3, p, B1, B2, B3, psi), equations)
72
flux = surface_flux_function(u_inner, u_mirror, normal, equations) * norm_
73
noncons_flux = nonconservative_flux_function(u_inner, u_mirror, normal, equations) *
74
norm_
75
return flux, noncons_flux
76
end
77
78
boundary_conditions = (; x_neg = boundary_condition_velocity_slip_wall,
79
x_pos = boundary_condition_velocity_slip_wall,
80
y_neg = boundary_condition_do_nothing,
81
y_pos = BoundaryConditionDirichlet(initial_condition))
82
83
semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver;
84
boundary_conditions = boundary_conditions)
85
86
###############################################################################
87
# ODE solvers, callbacks etc.
88
89
tspan = (0.0, 0.075)
90
ode = semidiscretize(semi, tspan)
91
92
summary_callback = SummaryCallback()
93
94
analysis_interval = 100
95
analysis_callback = AnalysisCallback(semi, interval = analysis_interval,
96
uEltype = real(solver))
97
alive_callback = AliveCallback(alive_interval = 10)
98
99
cfl = 0.5
100
stepsize_callback = StepsizeCallback(cfl = cfl)
101
glm_speed_callback = GlmSpeedCallback(glm_scale = 0.5, cfl = cfl)
102
103
save_solution = SaveSolutionCallback(interval = analysis_interval,
104
solution_variables = cons2prim)
105
106
callbacks = CallbackSet(summary_callback,
107
analysis_callback,
108
alive_callback,
109
stepsize_callback,
110
glm_speed_callback,
111
save_solution)
112
113
###############################################################################
114
# run the simulation
115
116
sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false);
117
dt = 1e-5, # solve needs some value here but it will be overwritten by the stepsize_callback
118
ode_default_options()..., callback = callbacks);
119
120