Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
5 changes: 3 additions & 2 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,10 @@ for human readability.
## Changes in the v0.13 lifecycle

#### Added
- Initial 3D support for subcell limiting with `P4estMesh` was added ([#2582]).
- Initial 3D support for subcell limiting with `P4estMesh` was added ([#2582] and [#2647]).
In the new version, IDP positivity limiting for conservative variables (using
the keyword `positivity_variables_cons` in `SubcellLimiterIDP()`) is supported.
the keyword `positivity_variables_cons` in `SubcellLimiterIDP()`) and nonlinear
variables (using `positivity_variables_nonlinear`) is supported.
`BoundsCheckCallback` is not supported in 3D yet.
- Optimized 2D and 3D kernels for nonconservative fluxes with `P4estMesh` were added ([#2653], [#2663]).
The optimized kernel can be enabled via the trait `Trixi.combine_conservative_and_nonconservative_fluxes(flux, equations)`.
Expand Down
6 changes: 3 additions & 3 deletions examples/p4est_3d_dgsem/elixir_euler_sedov_sc_subcell.jl
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ function initial_condition_sedov_blast_wave(x, t,
r0 = 0.21875 # = 3.5 * smallest dx (for domain length=4 and max-ref=6)
E = 1.0
p0_inner = 3 * (equations.gamma - 1) * E / (4 * pi * r0^2)
p0_outer = 1.0e-1 # "simpler" setup since positivity limiter for pressure is not yet supported in 3D
p0_outer = 1.0e-5 # = true Sedov setup

# Calculate primitive variables
rho = 1.0
Expand All @@ -36,15 +36,15 @@ function initial_condition_sedov_blast_wave(x, t,

return prim2cons(SVector(rho, v1, v2, v3, p), equations)
end

initial_condition = initial_condition_sedov_blast_wave

surface_flux = flux_lax_friedrichs
volume_flux = flux_ranocha
polydeg = 3
basis = LobattoLegendreBasis(polydeg)
limiter_idp = SubcellLimiterIDP(equations, basis;
positivity_variables_cons = ["rho"])
positivity_variables_cons = ["rho"],
positivity_variables_nonlinear = [pressure])
volume_integral = VolumeIntegralSubcellLimiting(limiter_idp;
volume_flux_dg = volume_flux,
volume_flux_fv = surface_flux)
Expand Down
3 changes: 1 addition & 2 deletions src/equations/compressible_euler_2d.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2232,8 +2232,7 @@ end

# State validation for Newton-bisection method of subcell IDP limiting
@inline function Base.isvalid(u, equations::CompressibleEulerEquations2D)
p = pressure(u, equations)
if u[1] <= 0 || p <= 0
if u[1] <= 0 || pressure(u, equations) <= 0
return false
end
return true
Expand Down
8 changes: 8 additions & 0 deletions src/equations/compressible_euler_3d.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1898,4 +1898,12 @@ end
@inline function energy_internal(cons, equations::CompressibleEulerEquations3D)
return energy_total(cons, equations) - energy_kinetic(cons, equations)
end

# State validation for Newton-bisection method of subcell IDP limiting
@inline function Base.isvalid(u, equations::CompressibleEulerEquations3D)
if u[1] <= 0 || pressure(u, equations) <= 0
return false
end
return true
end
end # @muladd
104 changes: 104 additions & 0 deletions src/solvers/dgsem_p4est/subcell_limiters_3d.jl
Original file line number Diff line number Diff line change
Expand Up @@ -73,4 +73,108 @@

return nothing
end

###############################################################################
# Global positivity limiting of nonlinear variables

@inline function idp_positivity_nonlinear!(alpha, limiter,
u::AbstractArray{<:Real, 5}, dt, semi,
variable)
mesh, equations, dg, cache = mesh_equations_solver_cache(semi)
(; positivity_correction_factor) = limiter

(; variable_bounds) = limiter.cache.subcell_limiter_coefficients
var_min = variable_bounds[Symbol(string(variable), "_min")]

@threaded for element in eachelement(dg, semi.cache)
for k in eachnode(dg), j in eachnode(dg), i in eachnode(dg)
inverse_jacobian = get_inverse_jacobian(cache.elements.inverse_jacobian,
mesh, i, j, k, element)

# Compute bound
u_local = get_node_vars(u, equations, dg, i, j, k, element)
var = variable(u_local, equations)
if var < 0
error("Safe low-order method produces negative value for variable $variable. Try a smaller time step.")
end
var_min[i, j, k, element] = positivity_correction_factor * var

# Perform Newton's bisection method to find new alpha
newton_loops_alpha!(alpha, var_min[i, j, k, element],
u_local, i, j, k, element,
variable, min,
initial_check_nonnegative_newton_idp,
final_check_nonnegative_newton_idp,
inverse_jacobian, dt, equations, dg, cache, limiter)
end
end

return nothing
end

###############################################################################
# Newton-bisection method

@inline function newton_loops_alpha!(alpha, bound, u, i, j, k, element,
variable, min_or_max,
initial_check, final_check,
inverse_jacobian, dt,
equations, dg, cache, limiter)
(; inverse_weights) = dg.basis # Plays role of inverse DG-subcell sizes
(; antidiffusive_flux1_L, antidiffusive_flux1_R, antidiffusive_flux2_L, antidiffusive_flux2_R, antidiffusive_flux3_L, antidiffusive_flux3_R) = cache.antidiffusive_fluxes

(; gamma_constant_newton) = limiter

indices = (i, j, k, element)

# negative xi direction
antidiffusive_flux = gamma_constant_newton * inverse_jacobian *
inverse_weights[i] *
get_node_vars(antidiffusive_flux1_R, equations, dg,
i, j, k, element)
newton_loop!(alpha, bound, u, indices, variable, min_or_max,
initial_check, final_check, equations, dt, limiter, antidiffusive_flux)

# positive xi direction
antidiffusive_flux = -gamma_constant_newton * inverse_jacobian *
inverse_weights[i] *
get_node_vars(antidiffusive_flux1_L, equations, dg,
i + 1, j, k, element)
newton_loop!(alpha, bound, u, indices, variable, min_or_max,
initial_check, final_check, equations, dt, limiter, antidiffusive_flux)

# negative eta direction
antidiffusive_flux = gamma_constant_newton * inverse_jacobian *
inverse_weights[j] *
get_node_vars(antidiffusive_flux2_R, equations, dg,
i, j, k, element)
newton_loop!(alpha, bound, u, indices, variable, min_or_max,
initial_check, final_check, equations, dt, limiter, antidiffusive_flux)

# positive eta direction
antidiffusive_flux = -gamma_constant_newton * inverse_jacobian *
inverse_weights[j] *
get_node_vars(antidiffusive_flux2_L, equations, dg,
i, j + 1, k, element)
newton_loop!(alpha, bound, u, indices, variable, min_or_max,
initial_check, final_check, equations, dt, limiter, antidiffusive_flux)

# negative zeta direction
antidiffusive_flux = gamma_constant_newton * inverse_jacobian *
inverse_weights[k] *
get_node_vars(antidiffusive_flux3_R, equations, dg,
i, j, k, element)
newton_loop!(alpha, bound, u, indices, variable, min_or_max,
initial_check, final_check, equations, dt, limiter, antidiffusive_flux)

# positive zeta direction
antidiffusive_flux = -gamma_constant_newton * inverse_jacobian *
inverse_weights[k] *
get_node_vars(antidiffusive_flux3_L, equations, dg,
i, j, k + 1, element)
newton_loop!(alpha, bound, u, indices, variable, min_or_max,
initial_check, final_check, equations, dt, limiter, antidiffusive_flux)

return nothing
end
end # @muladd
22 changes: 11 additions & 11 deletions test/test_p4est_3d.jl
Original file line number Diff line number Diff line change
Expand Up @@ -327,20 +327,20 @@ end
@trixi_testset "elixir_euler_sedov_sc_subcell.jl" begin
@test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_sedov_sc_subcell.jl"),
l2=[
0.16371327294681623,
0.0779033135575244,
0.07790331355752474,
0.07790331355752393,
0.36689870760596666
0.1942700455652903,
0.07557644365785855,
0.07557644365785836,
0.07557644365785698,
0.3713893635249306
],
linf=[
4.210879608740924,
2.881468426664787,
2.8814684266647874,
2.8814684266647856,
6.002617193075404
2.7542157588958798,
1.8885700263691245,
1.888570026369125,
1.8885700263691252,
4.9712792944452096
],
tspan=(0.0, 0.2),)
tspan=(0.0, 0.3),)
# Ensure that we do not have excessive memory allocations
# (e.g., from type instabilities)
# Larger values for allowed allocations due to usage of custom
Expand Down
Loading