Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement subcell limiting for non-conservative systems #1670

Merged
merged 49 commits into from
Oct 31, 2023
Merged
Show file tree
Hide file tree
Changes from 37 commits
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
99c1782
Added first (ugly) implementation of subcell limiting for non-conserv…
amrueda Oct 5, 2023
67e379f
Modified non-conservative fluxes to revert src/solvers/dgsem_tree/dg_…
amrueda Oct 6, 2023
12c6c1d
Subcell limiting: Added the possibility to use multiple nonconservati…
amrueda Oct 10, 2023
7017914
Added some comments and improved formatting
amrueda Oct 10, 2023
5119d97
Added expected results for MHD subcell limiting test
amrueda Oct 10, 2023
ad6177e
Restored old Powell source term and created a new function name for t…
amrueda Oct 10, 2023
9158093
Fixed bug
amrueda Oct 10, 2023
3dcccc4
Fixed bug
amrueda Oct 10, 2023
adb930e
Moved new multiple-dispatch structs for to equations.jl
amrueda Oct 11, 2023
b0e3aad
Improved allocations
amrueda Oct 11, 2023
e0a3fdf
Avoid double computation of local part of non-conservative flux
amrueda Oct 11, 2023
86884e8
Improved subcell volume integral in y direction and formatting
amrueda Oct 11, 2023
0d61cfd
Apply suggestions from code review
amrueda Oct 12, 2023
b0caf8e
Added timers and corrected docstrings
amrueda Oct 12, 2023
6dae80a
Improved formatting
amrueda Oct 12, 2023
0c2e24e
Reduced testing time
amrueda Oct 12, 2023
20abe7b
Renamed variables for consistency
amrueda Oct 16, 2023
505cbbb
Merge branch 'main' into subcell_limiting_noncons
amrueda Oct 16, 2023
cf05403
Removed some unnecessary operations in the Powell/GLM non-conservativ…
amrueda Oct 16, 2023
c2ec8c1
Added two elixirs to compare performance
amrueda Oct 17, 2023
781e839
avoid repeated memory writing/reading
ranocha Oct 20, 2023
c3377ec
format
ranocha Oct 20, 2023
a1131d9
Merge branch 'main' into subcell_limiting_noncons
ranocha Oct 20, 2023
4729149
Merge branch 'main' into subcell_limiting_noncons
amrueda Oct 23, 2023
842399d
Replaced scalar-vector product with scalar-scalar product
amrueda Oct 23, 2023
4fa45bc
Removed timers that are not compatible with multi-threading
amrueda Oct 23, 2023
e40f0ea
Added bounds check for GLM-MHD subcell positivity example
amrueda Oct 23, 2023
9053e17
Removed unneeded elixirs
amrueda Oct 23, 2023
6605c41
format
amrueda Oct 23, 2023
2b21e6a
Cherry-picked changes done in PR (https://github.com/bennibolm/Trixi.…
amrueda Oct 20, 2023
10cb3b2
Merge branch 'main' into subcell_limiting_noncons
sloede Oct 23, 2023
41dc2a1
Apply suggestions from code review
amrueda Oct 23, 2023
50be874
Renamed flux_nonconservative_powell2 to flux_nonconservative_powell_l…
amrueda Oct 24, 2023
e7d1b08
Merge branch 'main' into subcell_limiting_noncons
amrueda Oct 24, 2023
c7c3ca0
Increased maximum allowed allocation bound for subcell limiting simul…
amrueda Oct 24, 2023
120f9ba
Added explanatory comments about different non-conservative fluxes an…
amrueda Oct 24, 2023
81d40e2
Changed variable name noncons_term to nonconservative_term
amrueda Oct 24, 2023
c7dd7f5
Update docstrin of flux_nonconservative_powell_local_symmetric
amrueda Oct 24, 2023
7910993
Renamed function nnoncons as n_nonconservative_terms
amrueda Oct 24, 2023
3f9f0fe
format
amrueda Oct 24, 2023
b6646ad
Apply suggestions from code review
amrueda Oct 24, 2023
0eee721
Non-conservative subcell limiting cache only allocated for non-conser…
amrueda Oct 24, 2023
df12f03
Merge branch 'main' into subcell_limiting_noncons
amrueda Oct 24, 2023
91662db
Merge branch 'main' into subcell_limiting_noncons
ranocha Oct 25, 2023
f0b3ea4
Update src/equations/equations.jl
amrueda Oct 25, 2023
cc4b4fa
Declare `n_nonconservative_terms` in equations.jl as a function witho…
amrueda Oct 25, 2023
48f7c14
Changed if
amrueda Oct 25, 2023
4e65fe0
Merge branch 'main' into subcell_limiting_noncons
amrueda Oct 30, 2023
e836b7f
format
amrueda Oct 30, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
108 changes: 108 additions & 0 deletions examples/tree_2d_dgsem/elixir_mhd_shockcapturing_subcell.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@

using OrdinaryDiffEq
using Trixi

###############################################################################
# semidiscretization of the compressible ideal GLM-MHD equations

equations = IdealGlmMhdEquations2D(1.4)

"""
initial_condition_blast_wave(x, t, equations::IdealGlmMhdEquations2D)

An MHD blast wave modified from:
- Dominik Derigs, Gregor J. Gassner, Stefanie Walch & Andrew R. Winters (2018)
Entropy Stable Finite Volume Approximations for Ideal Magnetohydrodynamics
[doi: 10.1365/s13291-018-0178-9](https://doi.org/10.1365/s13291-018-0178-9)
This setup needs a positivity limiter for the density.
"""
function initial_condition_blast_wave(x, t, equations::IdealGlmMhdEquations2D)
# setup taken from Derigs et al. DMV article (2018)
# domain must be [-0.5, 0.5] x [-0.5, 0.5], γ = 1.4
r = sqrt(x[1]^2 + x[2]^2)

pmax = 10.0
pmin = 1.0
rhomax = 1.0
rhomin = 0.01
if r <= 0.09
p = pmax
rho = rhomax
elseif r >= 0.1
p = pmin
rho = rhomin
else
p = pmin + (0.1 - r) * (pmax - pmin) / 0.01
rho = rhomin + (0.1 - r) * (rhomax - rhomin) / 0.01
end
v1 = 0.0
v2 = 0.0
v3 = 0.0
B1 = 1.0/sqrt(4.0*pi)
B2 = 0.0
B3 = 0.0
psi = 0.0
return prim2cons(SVector(rho, v1, v2, v3, p, B1, B2, B3, psi), equations)
end
initial_condition = initial_condition_blast_wave

surface_flux = (flux_lax_friedrichs, flux_nonconservative_powell_local_symmetric)
volume_flux = (flux_derigs_etal, flux_nonconservative_powell_local_symmetric)
basis = LobattoLegendreBasis(3)

limiter_idp = SubcellLimiterIDP(equations, basis;
positivity_variables_cons=[1],
positivity_correction_factor=0.5)
volume_integral = VolumeIntegralSubcellLimiting(limiter_idp;
volume_flux_dg=volume_flux,
volume_flux_fv=surface_flux)
solver = DGSEM(basis, surface_flux, volume_integral)

coordinates_min = (-0.5, -0.5)
coordinates_max = ( 0.5, 0.5)
mesh = TreeMesh(coordinates_min, coordinates_max,
initial_refinement_level=4,
n_cells_max=10_000)


semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver)


###############################################################################
# ODE solvers, callbacks etc.

tspan = (0.0, 0.1)
ode = semidiscretize(semi, tspan)

summary_callback = SummaryCallback()

analysis_interval = 100
analysis_callback = AnalysisCallback(semi, interval=analysis_interval)

alive_callback = AliveCallback(analysis_interval=analysis_interval)

save_solution = SaveSolutionCallback(interval=100,
save_initial_solution=true,
save_final_solution=true,
solution_variables=cons2prim)

cfl = 0.5
stepsize_callback = StepsizeCallback(cfl=cfl)

glm_speed_callback = GlmSpeedCallback(glm_scale=0.5, cfl=cfl)

callbacks = CallbackSet(summary_callback,
analysis_callback,
alive_callback,
save_solution,
stepsize_callback,
glm_speed_callback)

###############################################################################
# run the simulation
stage_callbacks = (SubcellLimiterIDPCorrection(), BoundsCheckCallback())

sol = Trixi.solve(ode, Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks);
dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback
save_everystep=false, callback=callbacks);
summary_callback() # print the timer summary
2 changes: 1 addition & 1 deletion src/Trixi.jl
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ export GradientVariablesPrimitive, GradientVariablesEntropy
export flux, flux_central, flux_lax_friedrichs, flux_hll, flux_hllc, flux_hlle,
flux_godunov,
flux_chandrashekar, flux_ranocha, flux_derigs_etal, flux_hindenlang_gassner,
flux_nonconservative_powell,
flux_nonconservative_powell, flux_nonconservative_powell_local_symmetric,
flux_kennedy_gruber, flux_shima_etal, flux_ec,
flux_fjordholm_etal, flux_nonconservative_fjordholm_etal, flux_es_fjordholm_etal,
flux_wintermeyer_etal, flux_nonconservative_wintermeyer_etal,
Expand Down
10 changes: 5 additions & 5 deletions src/callbacks_stage/subcell_limiter_idp_correction_2d.jl
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

function perform_idp_correction!(u, dt, mesh::TreeMesh2D, equations, dg, cache)
@unpack inverse_weights = dg.basis
@unpack antidiffusive_flux1, antidiffusive_flux2 = cache.antidiffusive_fluxes
@unpack antidiffusive_flux1_L, antidiffusive_flux2_L, antidiffusive_flux1_R, antidiffusive_flux2_R = cache.antidiffusive_fluxes
@unpack alpha1, alpha2 = dg.volume_integral.limiter.cache.subcell_limiter_coefficients

@threaded for element in eachelement(dg, cache)
Expand All @@ -17,16 +17,16 @@ function perform_idp_correction!(u, dt, mesh::TreeMesh2D, equations, dg, cache)
for j in eachnode(dg), i in eachnode(dg)
# Note: antidiffusive_flux1[v, i, xi, element] = antidiffusive_flux2[v, xi, i, element] = 0 for all i in 1:nnodes and xi in {1, nnodes+1}
alpha_flux1 = (1 - alpha1[i, j, element]) *
get_node_vars(antidiffusive_flux1, equations, dg, i, j,
get_node_vars(antidiffusive_flux1_R, equations, dg, i, j,
element)
alpha_flux1_ip1 = (1 - alpha1[i + 1, j, element]) *
get_node_vars(antidiffusive_flux1, equations, dg, i + 1,
get_node_vars(antidiffusive_flux1_L, equations, dg, i + 1,
j, element)
alpha_flux2 = (1 - alpha2[i, j, element]) *
get_node_vars(antidiffusive_flux2, equations, dg, i, j,
get_node_vars(antidiffusive_flux2_R, equations, dg, i, j,
element)
alpha_flux2_jp1 = (1 - alpha2[i, j + 1, element]) *
get_node_vars(antidiffusive_flux2, equations, dg, i,
get_node_vars(antidiffusive_flux2_L, equations, dg, i,
j + 1, element)

for v in eachvariable(equations)
Expand Down
24 changes: 24 additions & 0 deletions src/equations/equations.jl
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,24 @@ struct BoundaryConditionNeumann{B}
boundary_normal_flux_function::B
end

"""
NonConservativeLocal()

Struct used for multiple dispatch on non-conservative flux functions in the format of "local * symmetric".
When the argument `nonconservative_type` is of type `NonConservativeLocal`,
the function returns the local part of the non-conservative term.
"""
struct NonConservativeLocal end

"""
NonConservativeSymmetric()

Struct used for multiple dispatch on non-conservative flux functions in the format of "local * symmetric".
When the argument `nonconservative_type` is of type `NonConservativeSymmetric`,
the function returns the symmetric part of the non-conservative term.
"""
struct NonConservativeSymmetric end

# set sensible default values that may be overwritten by specific equations
"""
have_nonconservative_terms(equations)
Expand All @@ -220,6 +238,12 @@ example of equations with nonconservative terms.
The return value will be `True()` or `False()` to allow dispatching on the return type.
"""
have_nonconservative_terms(::AbstractEquations) = False()
"""
nnoncons(equations)
Number of nonconservative terms for a particular equation. The default is 0 and
it must be defined for each nonconservative equation independently.
"""
nnoncons(::AbstractEquations) = 0
amrueda marked this conversation as resolved.
Show resolved Hide resolved
have_constant_speed(::AbstractEquations) = False()

default_analysis_errors(::AbstractEquations) = (:l2_error, :linf_error)
Expand Down
190 changes: 190 additions & 0 deletions src/equations/ideal_glm_mhd_2d.jl
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ function IdealGlmMhdEquations2D(gamma; initial_c_h = convert(typeof(gamma), NaN)
end

have_nonconservative_terms(::IdealGlmMhdEquations2D) = True()
nnoncons(::IdealGlmMhdEquations2D) = 2

function varnames(::typeof(cons2cons), ::IdealGlmMhdEquations2D)
("rho", "rho_v1", "rho_v2", "rho_v3", "rho_e", "B1", "B2", "B3", "psi")
end
Expand Down Expand Up @@ -279,6 +281,194 @@ end
return f
end

"""
flux_nonconservative_powell_local_symmetric(u_ll, u_rr,
orientation::Integer,
equations::IdealGlmMhdEquations2D)

Non-symmetric two-point flux discretizing the nonconservative (source) term of
Powell and the Galilean nonconservative term associated with the GLM multiplier
of the [`IdealGlmMhdEquations2D`](@ref).

This implementation uses a non-conservative term that can be written as the product
of local and symmetric parts. It is equivalent to the non-conservative flux of Bohm
et al. (`flux_nonconservative_powell`) for conforming meshes but it yields different
results on non-conforming meshes(!).
amrueda marked this conversation as resolved.
Show resolved Hide resolved

The two functions below, which share the same name, return yield either the local
amrueda marked this conversation as resolved.
Show resolved Hide resolved
or symmetric portion of the non-conservative flux based on the type of the
nonconservative_type argument, employing multiple dispatch. They are used to
compute the subcell fluxes in dg_2d_subcell_limiters.jl.

## References
- Rueda-Ramírez, Gassner (2023). A Flux-Differencing Formula for Split-Form Summation By Parts
Discretizations of Non-Conservative Systems. https://arxiv.org/pdf/2211.14009.pdf.
"""
@inline function flux_nonconservative_powell_local_symmetric(u_ll, u_rr,
orientation::Integer,
equations::IdealGlmMhdEquations2D)
rho_ll, rho_v1_ll, rho_v2_ll, rho_v3_ll, rho_e_ll, B1_ll, B2_ll, B3_ll, psi_ll = u_ll
rho_rr, rho_v1_rr, rho_v2_rr, rho_v3_rr, rho_e_rr, B1_rr, B2_rr, B3_rr, psi_rr = u_rr

v1_ll = rho_v1_ll / rho_ll
v2_ll = rho_v2_ll / rho_ll
v3_ll = rho_v3_ll / rho_ll
v_dot_B_ll = v1_ll * B1_ll + v2_ll * B2_ll + v3_ll * B3_ll

# Powell nonconservative term: (0, B_1, B_2, B_3, v⋅B, v_1, v_2, v_3, 0)
# Galilean nonconservative term: (0, 0, 0, 0, ψ v_{1,2}, 0, 0, 0, v_{1,2})
psi_avg = (psi_ll + psi_rr) #* 0.5 # We remove the 0.5 because the flux is always multiplied by 0.5
amrueda marked this conversation as resolved.
Show resolved Hide resolved
if orientation == 1
B1_avg = (B1_ll + B1_rr) #* 0.5 # We remove the 0.5 because the flux is always multiplied by 0.5
f = SVector(0,
B1_ll * B1_avg,
B2_ll * B1_avg,
B3_ll * B1_avg,
v_dot_B_ll * B1_avg + v1_ll * psi_ll * psi_avg,
v1_ll * B1_avg,
v2_ll * B1_avg,
v3_ll * B1_avg,
v1_ll * psi_avg)
else # orientation == 2
B2_avg = (B2_ll + B2_rr) #* 0.5 # We remove the 0.5 because the flux is always multiplied by 0.5
amrueda marked this conversation as resolved.
Show resolved Hide resolved
f = SVector(0,
B1_ll * B2_avg,
B2_ll * B2_avg,
B3_ll * B2_avg,
v_dot_B_ll * B2_avg + v2_ll * psi_ll * psi_avg,
v1_ll * B2_avg,
v2_ll * B2_avg,
v3_ll * B2_avg,
v2_ll * psi_avg)
end

return f
end

"""
flux_nonconservative_powell_local_symmetric(u_ll, orientation::Integer,
equations::IdealGlmMhdEquations2D,
nonconservative_type::NonConservativeLocal,
nonconservative_term::Integer)

Local part of the Powell and GLM non-conservative terms. Needed for the calculation of
the non-conservative staggered "fluxes" for subcell limiting. See, e.g.,
- Rueda-Ramírez, Gassner (2023). A Flux-Differencing Formula for Split-Form Summation By Parts
Discretizations of Non-Conservative Systems. https://arxiv.org/pdf/2211.14009.pdf.
This function is used to compute the subcell fluxes in dg_2d_subcell_limiters.jl.
"""
@inline function flux_nonconservative_powell_local_symmetric(u_ll, orientation::Integer,
equations::IdealGlmMhdEquations2D,
nonconservative_type::NonConservativeLocal,
nonconservative_term::Integer)
rho_ll, rho_v1_ll, rho_v2_ll, rho_v3_ll, rho_e_ll, B1_ll, B2_ll, B3_ll, psi_ll = u_ll

if nonconservative_term == 1
# Powell nonconservative term: (0, B_1, B_2, B_3, v⋅B, v_1, v_2, v_3, 0)
v1_ll = rho_v1_ll / rho_ll
v2_ll = rho_v2_ll / rho_ll
v3_ll = rho_v3_ll / rho_ll
v_dot_B_ll = v1_ll * B1_ll + v2_ll * B2_ll + v3_ll * B3_ll
f = SVector(0,
B1_ll,
B2_ll,
B3_ll,
v_dot_B_ll,
v1_ll,
v2_ll,
v3_ll,
0)
else #nonconservative_term ==2
# Galilean nonconservative term: (0, 0, 0, 0, ψ v_{1,2}, 0, 0, 0, v_{1,2})
if orientation == 1
v1_ll = rho_v1_ll / rho_ll
f = SVector(0,
0,
0,
0,
v1_ll * psi_ll,
0,
0,
0,
v1_ll)
else #orientation == 2
v2_ll = rho_v2_ll / rho_ll
f = SVector(0,
0,
0,
0,
v2_ll * psi_ll,
0,
0,
0,
v2_ll)
end
end
return f
end

"""
flux_nonconservative_powell_local_symmetric(u_ll, orientation::Integer,
equations::IdealGlmMhdEquations2D,
nonconservative_type::NonConservativeSymmetric,
nonconservative_term::Integer)

Symmetric part of the Powell and GLM non-conservative terms. Needed for the calculation of
the non-conservative staggered "fluxes" for subcell limiting. See, e.g.,
- Rueda-Ramírez, Gassner (2023). A Flux-Differencing Formula for Split-Form Summation By Parts
Discretizations of Non-Conservative Systems. https://arxiv.org/pdf/2211.14009.pdf.
This function is used to compute the subcell fluxes in dg_2d_subcell_limiters.jl.
"""
@inline function flux_nonconservative_powell_local_symmetric(u_ll, u_rr,
orientation::Integer,
equations::IdealGlmMhdEquations2D,
nonconservative_type::NonConservativeSymmetric,
nonconservative_term::Integer)
rho_ll, rho_v1_ll, rho_v2_ll, rho_v3_ll, rho_e_ll, B1_ll, B2_ll, B3_ll, psi_ll = u_ll
rho_rr, rho_v1_rr, rho_v2_rr, rho_v3_rr, rho_e_rr, B1_rr, B2_rr, B3_rr, psi_rr = u_rr

if nonconservative_term == 1
# Powell nonconservative term: (0, B_1, B_2, B_3, v⋅B, v_1, v_2, v_3, 0)
if orientation == 1
B1_avg = (B1_ll + B1_rr)#* 0.5 # We remove the 0.5 because the flux is always multiplied by 0.5
amrueda marked this conversation as resolved.
Show resolved Hide resolved
f = SVector(0,
B1_avg,
B1_avg,
B1_avg,
B1_avg,
B1_avg,
B1_avg,
B1_avg,
0)
else # orientation == 2
B2_avg = (B2_ll + B2_rr)#* 0.5 # We remove the 0.5 because the flux is always multiplied by 0.5
amrueda marked this conversation as resolved.
Show resolved Hide resolved
f = SVector(0,
B2_avg,
B2_avg,
B2_avg,
B2_avg,
B2_avg,
B2_avg,
B2_avg,
0)
end
else #nonconservative_term == 2
# Galilean nonconservative term: (0, 0, 0, 0, ψ v_{1,2}, 0, 0, 0, v_{1,2})
psi_avg = (psi_ll + psi_rr)#* 0.5 # We remove the 0.5 because the flux is always multiplied by 0.5
amrueda marked this conversation as resolved.
Show resolved Hide resolved
f = SVector(0,
0,
0,
0,
psi_avg,
0,
0,
0,
psi_avg)
end

return f
end

"""
flux_derigs_etal(u_ll, u_rr, orientation, equations::IdealGlmMhdEquations2D)

Expand Down
Loading
Loading