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

Second-Order Finite Volume Integral in 1D #2022

Open
wants to merge 37 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 22 commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
0975ed6
Pick up where Gregor left
DanielDoehring Jul 18, 2024
5c8c327
preliminary example
DanielDoehring Jul 18, 2024
0878422
more limiters
DanielDoehring Jul 19, 2024
80dd41b
comments
DanielDoehring Jul 19, 2024
059c660
fmt
DanielDoehring Jul 19, 2024
7f4afa6
continue
DanielDoehring Jul 23, 2024
196854a
comments
DanielDoehring Jul 23, 2024
86aed4f
print some more info
DanielDoehring Jul 23, 2024
064fb10
Add unit tests
DanielDoehring Jul 23, 2024
8b0b729
add comment
DanielDoehring Jul 23, 2024
13138ee
Remove some alternative limiter implementations.
DanielDoehring Jul 23, 2024
2df840d
move, comments, fmt
DanielDoehring Jul 24, 2024
4424ee5
Use second order timestepping
DanielDoehring Jul 24, 2024
f42bb9f
debug superbee
DanielDoehring Jul 24, 2024
1a44499
prim2cons 1D Adv
DanielDoehring Jul 24, 2024
5bb0ab2
test
DanielDoehring Jul 24, 2024
5f3c63f
Merge branch 'main' into SecondOrderFiniteVolume1D
DanielDoehring Jul 24, 2024
c2aab4e
fmt, typo
DanielDoehring Jul 24, 2024
3d591c5
typos
DanielDoehring Jul 24, 2024
fdc590a
some more tests
DanielDoehring Jul 25, 2024
8aabfd5
fmt
DanielDoehring Jul 25, 2024
573707e
Merge branch 'main' into SecondOrderFiniteVolume1D
DanielDoehring Aug 8, 2024
072ca29
Update src/solvers/dgsem_tree/finite_volume_O2.jl
DanielDoehring Aug 10, 2024
fa18a47
Update test/test_unit.jl
DanielDoehring Aug 10, 2024
a64bb60
Update src/solvers/dgsem_tree/dg_1d.jl
DanielDoehring Aug 10, 2024
0bcb5fc
Merge branch 'main' into SecondOrderFiniteVolume1D
DanielDoehring Sep 24, 2024
1e07939
Merge branch 'main' into SecondOrderFiniteVolume1D
DanielDoehring Sep 24, 2024
610dc24
fmt
DanielDoehring Sep 24, 2024
699d7e5
add different recontruction mode
DanielDoehring Oct 7, 2024
0773331
Update src/solvers/dgsem_tree/finite_volume_O2.jl
DanielDoehring Oct 7, 2024
d86900f
Merge branch 'main' into SecondOrderFiniteVolume1D
DanielDoehring Oct 7, 2024
9f71e16
test + fmt
DanielDoehring Oct 7, 2024
c9e9b6f
Merge branch 'SecondOrderFiniteVolume1D' of github.com:DanielDoehring…
DanielDoehring Oct 7, 2024
1f9bb57
comments
DanielDoehring Oct 7, 2024
20fe628
correct way cells dim
DanielDoehring Oct 7, 2024
ba708b9
increase coverage
DanielDoehring Oct 7, 2024
7b97473
Merge branch 'main' into SecondOrderFiniteVolume1D
DanielDoehring Oct 7, 2024
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
57 changes: 57 additions & 0 deletions examples/tree_1d_dgsem/elixir_euler_convergence_pure_fvO2.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@

using OrdinaryDiffEq
using Trixi

###############################################################################
# semidiscretization of the compressible Euler equations

equations = CompressibleEulerEquations1D(1.4)

initial_condition = initial_condition_convergence_test

polydeg = 3
basis = LobattoLegendreBasis(polydeg)
surf_flux = flux_hllc
solver = DGSEM(polydeg = polydeg, surface_flux = surf_flux,
volume_integral = VolumeIntegralPureLGLFiniteVolumeO2(basis,
volume_flux_fv = surf_flux,
slope_limiter = monotonized_central))

coordinates_min = 0.0
coordinates_max = 2.0
mesh = TreeMesh(coordinates_min, coordinates_max,
initial_refinement_level = 4,
n_cells_max = 10_000)

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

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

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

summary_callback = SummaryCallback()

analysis_interval = 100
analysis_callback = AnalysisCallback(semi, interval = analysis_interval,
extra_analysis_errors = (:l2_error_primitive,
:linf_error_primitive))

alive_callback = AliveCallback(analysis_interval = analysis_interval)

stepsize_callback = StepsizeCallback(cfl = 0.4)

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

###############################################################################
# run the simulation

sol = solve(ode, SSPRK22(),
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
6 changes: 5 additions & 1 deletion src/Trixi.jl
Original file line number Diff line number Diff line change
Expand Up @@ -235,13 +235,17 @@ export DG,
FDSBP,
VolumeIntegralWeakForm, VolumeIntegralStrongForm,
VolumeIntegralFluxDifferencing,
VolumeIntegralPureLGLFiniteVolume,
VolumeIntegralPureLGLFiniteVolume, VolumeIntegralPureLGLFiniteVolumeO2,
VolumeIntegralShockCapturingHG, IndicatorHennemannGassner,
VolumeIntegralUpwind,
SurfaceIntegralWeakForm, SurfaceIntegralStrongForm,
SurfaceIntegralUpwind,
MortarL2

export reconstruction_small_stencil, reconstruction_constant,
minmod, monotonized_central, superbee, vanLeer_limiter,
central_slope

export VolumeIntegralSubcellLimiting, BoundsCheckCallback,
SubcellLimiterIDP, SubcellLimiterIDPCorrection

Expand Down
2 changes: 2 additions & 0 deletions src/equations/linear_scalar_advection_1d.jl
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,8 @@ end

# Convert conservative variables to primitive
@inline cons2prim(u, equation::LinearScalarAdvectionEquation1D) = u
# Convert primitive variables to conservative
@inline prim2cons(u, equation::LinearScalarAdvectionEquation1D) = u

# Convert conservative variables to entropy variables
@inline cons2entropy(u, equation::LinearScalarAdvectionEquation1D) = u
Expand Down
2 changes: 2 additions & 0 deletions src/equations/linear_scalar_advection_2d.jl
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,8 @@ end

# Convert conservative variables to primitive
@inline cons2prim(u, equation::LinearScalarAdvectionEquation2D) = u
# Convert primitive variables to conservative
@inline prim2cons(u, equation::LinearScalarAdvectionEquation2D) = u

# Convert conservative variables to entropy variables
@inline cons2entropy(u, equation::LinearScalarAdvectionEquation2D) = u
Expand Down
2 changes: 2 additions & 0 deletions src/equations/linear_scalar_advection_3d.jl
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,8 @@ end

# Convert conservative variables to primitive
@inline cons2prim(u, equation::LinearScalarAdvectionEquation3D) = u
# Convert primitive variables to conservative
@inline prim2cons(u, equation::LinearScalarAdvectionEquation3D) = u

# Convert conservative variables to entropy variables
@inline cons2entropy(u, equation::LinearScalarAdvectionEquation3D) = u
Expand Down
59 changes: 59 additions & 0 deletions src/solvers/dg.jl
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,65 @@ function Base.show(io::IO, ::MIME"text/plain",
end
end

"""
VolumeIntegralPureLGLFiniteVolumeO2(basis::Basis;
volume_flux_fv = flux_lax_friedrichs,
reconstruction_mode = reconstruction_small_stencil,
slope_limiter = minmod)

This gives a formally O(2)-accurate finite volume scheme on an LGL-type subcell
mesh (LGL = Legendre-Gauss-Lobatto).
DanielDoehring marked this conversation as resolved.
Show resolved Hide resolved

!!! warning "Experimental implementation"
This is an experimental feature and may change in future releases.

## References

- Hennemann, Gassner (2020)
"A provably entropy stable subcell shock capturing approach for high order split form DG"
[arXiv: 2008.12044](https://arxiv.org/abs/2008.12044)
DanielDoehring marked this conversation as resolved.
Show resolved Hide resolved
"""
struct VolumeIntegralPureLGLFiniteVolumeO2{RealT, Basis, VolumeFluxFV, Reconstruction,
Limiter} <: AbstractVolumeIntegral
x_interfaces::Vector{RealT} # x-coordinates of the sub-cell element interfaces
volume_flux_fv::VolumeFluxFV # non-symmetric in general, e.g. entropy-dissipative
reconstruction_mode::Reconstruction # which type of FV reconstruction to use
slope_limiter::Limiter # which type of slope limiter function
end

function VolumeIntegralPureLGLFiniteVolumeO2(basis::Basis;
volume_flux_fv = flux_lax_friedrichs,
reconstruction_mode = reconstruction_small_stencil,
slope_limiter = minmod) where {Basis}
# Suffices to store only the intermediate boundaries of the sub-cell elements
x_interfaces = cumsum(basis.weights)[1:(end - 1)] .- 1
VolumeIntegralPureLGLFiniteVolumeO2{eltype(basis.weights),
typeof(basis),
typeof(volume_flux_fv),
typeof(reconstruction_mode),
typeof(slope_limiter)}(x_interfaces,
volume_flux_fv,
reconstruction_mode,
slope_limiter)
end

function Base.show(io::IO, ::MIME"text/plain",
integral::VolumeIntegralPureLGLFiniteVolumeO2)
@nospecialize integral # reduce precompilation time

if get(io, :compact, false)
show(io, integral)
else
setup = [
"FV flux" => integral.volume_flux_fv,
"Reconstruction" => integral.reconstruction_mode,
"Slope limiter" => integral.slope_limiter,
"Subcell boundaries" => vcat([-1.0], integral.x_interfaces, [1.0]),
]
summary_box(io, "VolumeIntegralPureLGLFiniteVolumeO2", setup)
end
end

"""
VolumeIntegralSubcellLimiting(limiter;
volume_flux_dg, volume_flux_fv)
Expand Down
3 changes: 3 additions & 0 deletions src/solvers/dgsem_tree/dg.jl
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,9 @@ include("dg_parallel.jl")
# Helper structs for parabolic AMR
include("containers_viscous.jl")

# Some standard functions for the canonical second-order FV (MUSCL) scheme
include("finite_volume_O2.jl")

# 1D DG implementation
include("dg_1d.jl")
include("dg_1d_parabolic.jl")
Expand Down
106 changes: 104 additions & 2 deletions src/solvers/dgsem_tree/dg_1d.jl
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,9 @@ end

function create_cache(mesh::Union{TreeMesh{1}, StructuredMesh{1}, P4estMesh{1}},
equations,
volume_integral::VolumeIntegralPureLGLFiniteVolume, dg::DG,
uEltype)
volume_integral::Union{VolumeIntegralPureLGLFiniteVolume,
VolumeIntegralPureLGLFiniteVolumeO2},
dg::DG, uEltype)
A2dp1_x = Array{uEltype, 2}
fstar1_L_threaded = A2dp1_x[A2dp1_x(undef, nvariables(equations), nnodes(dg) + 1)
for _ in 1:Threads.nthreads()]
Expand Down Expand Up @@ -309,6 +310,24 @@ function calc_volume_integral!(du, u,
return nothing
end

function calc_volume_integral!(du, u,
mesh::Union{TreeMesh{1}, StructuredMesh{1}},
nonconservative_terms, equations,
volume_integral::VolumeIntegralPureLGLFiniteVolumeO2,
dg::DGSEM, cache)
@unpack x_interfaces, volume_flux_fv, reconstruction_mode, slope_limiter = volume_integral

# Calculate LGL second-order FV volume integral
@threaded for element in eachelement(dg, cache)
fv_kernel!(du, u, mesh, nonconservative_terms, equations, volume_flux_fv,
dg, cache, element,
x_interfaces, reconstruction_mode, slope_limiter,
true)
end

return nothing
end

@inline function fv_kernel!(du, u,
mesh::Union{TreeMesh{1}, StructuredMesh{1}},
nonconservative_terms, equations,
Expand All @@ -335,6 +354,35 @@ end
return nothing
end

@inline function fv_kernel!(du, u,
mesh::Union{TreeMesh{1}, StructuredMesh{1}},
nonconservative_terms, equations,
volume_flux_fv, dg::DGSEM, cache, element,
x_interfaces, reconstruction_mode, slope_limiter,
alpha = true)
@unpack fstar1_L_threaded, fstar1_R_threaded = cache
@unpack inverse_weights = dg.basis

# Calculate FV two-point fluxes
fstar1_L = fstar1_L_threaded[Threads.threadid()]
fstar1_R = fstar1_R_threaded[Threads.threadid()]
calcflux_fv!(fstar1_L, fstar1_R, u, mesh, nonconservative_terms, equations,
volume_flux_fv,
dg, element, cache,
x_interfaces, reconstruction_mode, slope_limiter)

# Calculate FV volume integral contribution
for i in eachnode(dg)
for v in eachvariable(equations)
du[v, i, element] += (alpha *
(inverse_weights[i] *
(fstar1_L[v, i + 1] - fstar1_R[v, i])))
end
end

return nothing
end

@inline function calcflux_fv!(fstar1_L, fstar1_R, u::AbstractArray{<:Any, 3},
mesh::Union{TreeMesh{1}, StructuredMesh{1}},
nonconservative_terms::False,
Expand Down Expand Up @@ -388,6 +436,60 @@ end
return nothing
end

@inline function calcflux_fv!(fstar1_L, fstar1_R, u::AbstractArray{<:Any, 3},
mesh::Union{TreeMesh{1}, StructuredMesh{1}},
nonconservative_terms::False,
equations, volume_flux_fv, dg::DGSEM, element, cache,
x_interfaces, reconstruction_mode, slope_limiter)
fstar1_L[:, 1] .= zero(eltype(fstar1_L))
fstar1_L[:, nnodes(dg) + 1] .= zero(eltype(fstar1_L))
fstar1_R[:, 1] .= zero(eltype(fstar1_R))
fstar1_R[:, nnodes(dg) + 1] .= zero(eltype(fstar1_R))

for i in 2:nnodes(dg)
# Reference element:
# -1 -----------------0----------------- 1 -> x
# Gauss Lobatto Legendre nodes (schematic for k = 3):
DanielDoehring marked this conversation as resolved.
Show resolved Hide resolved
# . . . .
# ^ ^ ^ ^
# i - 2, i - 1, i, i + 1
# mm ll rr pp
# Cell boundaries (schematic for k = 3):
# (note that only the inner three boundaries are stored)
# -1 -----------------0----------------- 1 -> x
# | | | | |
# Cell index:
# 1 2 3 4

# Obtain unlimited values in primal variables

# Note: If i - 2 = 0 we do not go to neighbor element, as one would do in a finite volume scheme.
# Here, we keep it purely cell-local, thus overshoots between elements are not ruled out.
DanielDoehring marked this conversation as resolved.
Show resolved Hide resolved
u_mm = cons2prim(get_node_vars(u, equations, dg, max(1, i - 2), element),
equations)
u_ll = cons2prim(get_node_vars(u, equations, dg, i - 1, element), equations)
u_rr = cons2prim(get_node_vars(u, equations, dg, i, element), equations)
# Note: If i + 1 > nnodes(dg) we do not go to neighbor element, as one would do in a finite volume scheme.
# Here, we keep it purely cell-local, thus overshoots between elements are not ruled out.
u_pp = cons2prim(get_node_vars(u, equations, dg, min(nnodes(dg), i + 1),
element), equations)

# Reconstruct values at interfaces with limiting
u_ll, u_rr = reconstruction_mode(u_mm, u_ll, u_rr, u_pp,
x_interfaces,
i, slope_limiter, dg)

# Convert primal variables back to conservative variables
flux = volume_flux_fv(prim2cons(u_ll, equations), prim2cons(u_rr, equations),
1, equations) # orientation 1: x direction

set_node_vars!(fstar1_L, flux, equations, dg, i)
set_node_vars!(fstar1_R, flux, equations, dg, i)
end

return nothing
end

# We pass the `surface_integral` argument solely for dispatch
function prolong2interfaces!(cache, u,
mesh::TreeMesh{1}, equations, surface_integral, dg::DG)
Expand Down
Loading
Loading