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

Subcell positivity IDP limiting for conservative variables #1476

Merged
merged 46 commits into from
Aug 18, 2023
Merged
Show file tree
Hide file tree
Changes from 41 commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
d37fa21
Add IDP positivity limiting for conservative variables
bennibolm May 15, 2023
a139380
Add elixir with modified blast wave
bennibolm May 17, 2023
891526f
Add documentation
bennibolm May 17, 2023
a24ae11
Merge branch 'main' into IDPlimiting-positivity-cons
bennibolm May 22, 2023
b9ea8cf
Fix parameter type
bennibolm May 24, 2023
f228b0a
Adjust output of summary callback
bennibolm May 24, 2023
ea548da
Merge changes from `subcell-limiting` and `main`
bennibolm Jun 2, 2023
d801349
Merge branch 'main' into IDPlimiting-positivity-cons
bennibolm Jun 2, 2023
4359416
Fix test with right time stepping
bennibolm Jun 2, 2023
8f1f02f
Implement first suggestions
bennibolm Jun 3, 2023
68806e0
Implement suggestions
bennibolm Jun 5, 2023
cf66b94
Fix elixir
bennibolm Jun 5, 2023
a689a6c
Relocate `perform_idp_correction!`
bennibolm Jun 6, 2023
ecc4a18
Rename variable in `snake_case`
bennibolm Jun 6, 2023
8be446a
Implement other suggestions
bennibolm Jun 6, 2023
7acc24f
Rename container variables using `snake_case`
bennibolm Jun 6, 2023
6a46217
Delete timer
bennibolm Jun 6, 2023
e2262e5
Merge `subcell-limiting` (Adapt docstrings)
bennibolm Jun 6, 2023
70d3476
Merge `subcell-limiting`
bennibolm Jun 6, 2023
7979558
Merge `subcell-limiting` (Renaming and dispatch)
bennibolm Jun 10, 2023
b290d5b
Fix documentation
bennibolm Jun 10, 2023
01741c0
Merge branch 'main' into IDPlimiting-positivity-cons
bennibolm Jun 12, 2023
374fccf
Implement positivty limiter with numbers of cons vars
bennibolm Jun 14, 2023
a05a793
Merge branch 'main' into IDPlimiting-positivity-cons
bennibolm Jun 14, 2023
4e693d4
Merge branch 'IDPlimiting-positivity-cons' of https://github.com/benn…
bennibolm Jun 14, 2023
8dc8041
Merge branch 'main' into IDPlimiting-positivity-cons
bennibolm Jun 16, 2023
5f21d5d
Merge branch 'IDPlimiting-positivity-cons' into IDPlimiting-positivit…
bennibolm Jun 16, 2023
1ab075c
Merge suggestions already implemented in `subcell-limiting`
bennibolm Jun 16, 2023
3c7633d
Fix elixir
bennibolm Jun 16, 2023
43de3b7
Merge branch 'IDPlimiting-positivity-cons' into IDPlimiting-positivit…
bennibolm Jun 16, 2023
6cfbbff
Merge pull request #113 from bennibolm/IDPlimiting-positivity-cons-2
bennibolm Jun 19, 2023
b85e9b8
Merge branch 'main' into IDPlimiting-positivity-cons
bennibolm Jun 20, 2023
1785623
Merge branch 'IDPlimiting-positivity-cons' of https://github.com/benn…
bennibolm Jun 20, 2023
dd75ff6
Update docstring and output
bennibolm Jun 20, 2023
5cd186a
Restructure parameter for positivity limiting
bennibolm Jun 21, 2023
9d6d6f5
Add test for "show" routine
bennibolm Jun 21, 2023
7cb8597
Rename Limiters and Containers
bennibolm Jul 5, 2023
f4b6542
Rename antidiffusive stage callback
bennibolm Jul 6, 2023
0c634ed
Relocate subcell limiter code
bennibolm Jul 7, 2023
b055542
Move create_cache routine to specific file
bennibolm Jul 10, 2023
c287c96
Merge branch 'main' into IDPlimiting-positivity-cons
bennibolm Jul 10, 2023
111b334
Merge branch 'main' into IDPlimiting-positivity-cons
bennibolm Aug 9, 2023
0aad20b
Implement suggestions
bennibolm Aug 9, 2023
5c88cf2
Merge branch 'main' into IDPlimiting-positivity-cons
ranocha Aug 9, 2023
2b88d61
Merge branch 'main' into IDPlimiting-positivity-cons
sloede Aug 17, 2023
0fca290
Implement suggestions
bennibolm Aug 18, 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
92 changes: 92 additions & 0 deletions examples/tree_2d_dgsem/elixir_euler_shockcapturing_subcell.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@

using OrdinaryDiffEq
using Trixi

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

equations = CompressibleEulerEquations2D(1.4)

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

A medium blast wave (modified to lower density and higher pressure) taken from
- Sebastian Hennemann, Gregor J. 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)
"""
function initial_condition_blast_wave(x, t, equations::CompressibleEulerEquations2D)
# Modified From Hennemann & Gassner JCP paper 2020 (Sec. 6.3) -> modified to lower density, higher pressure
# Set up polar coordinates
inicenter = SVector(0.0, 0.0)
x_norm = x[1] - inicenter[1]
y_norm = x[2] - inicenter[2]
r = sqrt(x_norm^2 + y_norm^2)
phi = atan(y_norm, x_norm)
sin_phi, cos_phi = sincos(phi)

# Calculate primitive variables "normal" medium blast wave
rho = r > 0.5 ? 0.1 : 0.2691 # rho = r > 0.5 ? 1 : 1.1691
v1 = r > 0.5 ? 0.0 : 0.1882 * cos_phi
v2 = r > 0.5 ? 0.0 : 0.1882 * sin_phi
p = r > 0.5 ? 1.0E-1 : 1.245 # p = r > 0.5 ? 1.0E-3 : 1.245

return prim2cons(SVector(rho, v1, v2, p), equations)
end
initial_condition = initial_condition_blast_wave

surface_flux = flux_lax_friedrichs
volume_flux = flux_ranocha
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 = (-2.0, -2.0)
coordinates_max = ( 2.0, 2.0)
mesh = TreeMesh(coordinates_min, coordinates_max,
initial_refinement_level=5,
n_cells_max=100_000)

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


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

tspan = (0.0, 1.0)
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)

stepsize_callback = StepsizeCallback(cfl=0.6)

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


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

stage_callbacks = (SubcellLimiterIDPCorrection(),)

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
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
using OrdinaryDiffEq
using Trixi

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

# 1) Dry Air 2) Helium + 28% Air
equations = CompressibleEulerMulticomponentEquations2D(gammas = (1.4, 1.648),
gas_constants = (0.287, 1.578))

"""
initial_condition_shock_bubble(x, t, equations::CompressibleEulerMulticomponentEquations2D{5, 2})

A shock-bubble testcase for multicomponent Euler equations
- Ayoub Gouasmi, Karthik Duraisamy, Scott Murman
Formulation of Entropy-Stable schemes for the multicomponent compressible Euler equations
[arXiv: 1904.00972](https://arxiv.org/abs/1904.00972)
"""
function initial_condition_shock_bubble(x, t, equations::CompressibleEulerMulticomponentEquations2D{5, 2})
# bubble test case, see Gouasmi et al. https://arxiv.org/pdf/1904.00972
# other reference: https://www.researchgate.net/profile/Pep_Mulet/publication/222675930_A_flux-split_algorithm_applied_to_conservative_models_for_multicomponent_compressible_flows/links/568da54508aeaa1481ae7af0.pdf
# typical domain is rectangular, we change it to a square, as Trixi can only do squares
@unpack gas_constants = equations

# Positivity Preserving Parameter, can be set to zero if scheme is positivity preserving
delta = 0.03

# Region I
rho1_1 = delta
rho2_1 = 1.225 * gas_constants[1]/gas_constants[2] - delta
v1_1 = zero(delta)
v2_1 = zero(delta)
p_1 = 101325

# Region II
rho1_2 = 1.225-delta
rho2_2 = delta
v1_2 = zero(delta)
v2_2 = zero(delta)
p_2 = 101325

# Region III
rho1_3 = 1.6861 - delta
rho2_3 = delta
v1_3 = -113.5243
v2_3 = zero(delta)
p_3 = 159060

# Set up Region I & II:
inicenter = SVector(zero(delta), zero(delta))
x_norm = x[1] - inicenter[1]
y_norm = x[2] - inicenter[2]
r = sqrt(x_norm^2 + y_norm^2)

if (x[1] > 0.50)
# Set up Region III
rho1 = rho1_3
rho2 = rho2_3
v1 = v1_3
v2 = v2_3
p = p_3
elseif (r < 0.25)
# Set up Region I
rho1 = rho1_1
rho2 = rho2_1
v1 = v1_1
v2 = v2_1
p = p_1
else
# Set up Region II
rho1 = rho1_2
rho2 = rho2_2
v1 = v1_2
v2 = v2_2
p = p_2
end

return prim2cons(SVector(v1, v2, p, rho1, rho2), equations)
end
initial_condition = initial_condition_shock_bubble

surface_flux = flux_lax_friedrichs
volume_flux = flux_ranocha
basis = LobattoLegendreBasis(3)

limiter_idp = SubcellLimiterIDP(equations, basis;
positivity_variables_cons=[(i+3 for i in eachcomponent(equations))...])

volume_integral = VolumeIntegralSubcellLimiting(limiter_idp;
volume_flux_dg=volume_flux,
volume_flux_fv=surface_flux)

solver = DGSEM(basis, surface_flux, volume_integral)

coordinates_min = (-2.25, -2.225)
coordinates_max = ( 2.20, 2.225)
mesh = TreeMesh(coordinates_min, coordinates_max,
initial_refinement_level=3,
n_cells_max=1_000_000)

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


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

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

summary_callback = SummaryCallback()

analysis_interval = 300
analysis_callback = AnalysisCallback(semi, interval=analysis_interval,
extra_analysis_integrals=(Trixi.density,))

alive_callback = AliveCallback(analysis_interval=analysis_interval)

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

stepsize_callback = StepsizeCallback(cfl=0.9)

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


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

stage_callbacks = (SubcellLimiterIDPCorrection(),)

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
5 changes: 3 additions & 2 deletions src/Trixi.jl
Original file line number Diff line number Diff line change
Expand Up @@ -119,10 +119,10 @@ include("semidiscretization/semidiscretization_hyperbolic.jl")
include("semidiscretization/semidiscretization_hyperbolic_parabolic.jl")
include("semidiscretization/semidiscretization_euler_acoustics.jl")
include("semidiscretization/semidiscretization_coupled.jl")
include("time_integration/time_integration.jl")
include("callbacks_step/callbacks_step.jl")
include("callbacks_stage/callbacks_stage.jl")
include("semidiscretization/semidiscretization_euler_gravity.jl")
include("time_integration/time_integration.jl")

# `trixi_include` and special elixirs such as `convergence_test`
include("auxiliary/special_elixirs.jl")
Expand Down Expand Up @@ -215,6 +215,7 @@ export DG,
VolumeIntegralFluxDifferencing,
VolumeIntegralPureLGLFiniteVolume,
VolumeIntegralShockCapturingHG, IndicatorHennemannGassner,
VolumeIntegralSubcellLimiting, SubcellLimiterIDP,
VolumeIntegralUpwind,
SurfaceIntegralWeakForm, SurfaceIntegralStrongForm,
SurfaceIntegralUpwind,
Expand Down Expand Up @@ -248,7 +249,7 @@ export ControllerThreeLevel, ControllerThreeLevelCombined,
IndicatorNeuralNetwork, NeuralNetworkPerssonPeraire, NeuralNetworkRayHesthaven,
NeuralNetworkCNN

export PositivityPreservingLimiterZhangShu
export PositivityPreservingLimiterZhangShu, SubcellLimiterIDPCorrection
bennibolm marked this conversation as resolved.
Show resolved Hide resolved

export trixi_include, examples_dir, get_examples, default_example,
default_example_unstructured, ode_default_options
Expand Down
1 change: 1 addition & 0 deletions src/callbacks_stage/callbacks_stage.jl
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,5 @@
#! format: noindent

include("positivity_zhang_shu.jl")
include("subcell_limiter_idp_correction.jl")
end # @muladd
68 changes: 68 additions & 0 deletions src/callbacks_stage/subcell_limiter_idp_correction.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
# By default, Julia/LLVM does not use fused multiply-add operations (FMAs).
# Since these FMAs can increase the performance of many numerical algorithms,
# we need to opt-in explicitly.
# See https://ranocha.de/blog/Optimizing_EC_Trixi for further details.
@muladd begin
#! format: noindent

"""
SubcellLimiterIDPCorrection()

Perform antidiffusive correction stage for the a posteriori IDP limiter [`SubcellLimiterIDP`](@ref)
called with [`VolumeIntegralSubcellLimiting`](@ref).

!!! note
This callback and the actual limiter [`SubcellLimiterIDP`](@ref) only work together.
This is not a replacement but a necessary addition.

## References

- Rueda-Ramírez, Pazner, Gassner (2022)
Subcell Limiting Strategies for Discontinuous Galerkin Spectral Element Methods
[DOI: 10.1016/j.compfluid.2022.105627](https://doi.org/10.1016/j.compfluid.2022.105627)
- Pazner (2020)
Sparse invariant domain preserving discontinuous Galerkin methods with subcell convex limiting
[DOI: 10.1016/j.cma.2021.113876](https://doi.org/10.1016/j.cma.2021.113876)

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

function (limiter!::SubcellLimiterIDPCorrection)(u_ode,
integrator::Trixi.SimpleIntegratorSSP,
stage)
limiter!(u_ode, integrator.p, integrator.t, integrator.dt,
integrator.p.solver.volume_integral)
end
bennibolm marked this conversation as resolved.
Show resolved Hide resolved

function (limiter!::SubcellLimiterIDPCorrection)(u_ode, semi, t, dt,
volume_integral::VolumeIntegralSubcellLimiting)
sloede marked this conversation as resolved.
Show resolved Hide resolved
@trixi_timeit timer() "a posteriori limiter" limiter!(u_ode, semi, t, dt,
volume_integral.limiter)
end

function (limiter!::SubcellLimiterIDPCorrection)(u_ode, semi, t, dt,
limiter::SubcellLimiterIDP)
mesh, equations, solver, cache = mesh_equations_solver_cache(semi)

u = wrap_array(u_ode, mesh, equations, solver, cache)

# Calculate blending factor alpha in [0,1]
# f_ij = alpha_ij * f^(FV)_ij + (1 - alpha_ij) * f^(DG)_ij
# = f^(FV)_ij + (1 - alpha_ij) * f^(antidiffusive)_ij
@trixi_timeit timer() "blending factors" solver.volume_integral.limiter(u, semi,
solver, t,
dt)

perform_idp_correction!(u, dt, mesh, equations, solver, cache)

return nothing
end

init_callback(limiter!::SubcellLimiterIDPCorrection, semi) = nothing

finalize_callback(limiter!::SubcellLimiterIDPCorrection, semi) = nothing

include("subcell_limiter_idp_correction_2d.jl")
end # @muladd
44 changes: 44 additions & 0 deletions src/callbacks_stage/subcell_limiter_idp_correction_2d.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# By default, Julia/LLVM does not use fused multiply-add operations (FMAs).
# Since these FMAs can increase the performance of many numerical algorithms,
# we need to opt-in explicitly.
# See https://ranocha.de/blog/Optimizing_EC_Trixi for further details.
@muladd begin
#! format: noindent

@inline function perform_idp_correction!(u, dt, mesh::TreeMesh2D, equations, dg, cache)
bennibolm marked this conversation as resolved.
Show resolved Hide resolved
@unpack inverse_weights = dg.basis
@unpack antidiffusive_flux1, antidiffusive_flux2 = cache.container_antidiffusive_flux
@unpack alpha1, alpha2 = dg.volume_integral.limiter.cache.container_subcell_limiter

@threaded for element in eachelement(dg, cache)
# Sign switch as in apply_jacobian!
inverse_jacobian = -cache.elements.inverse_jacobian[element]

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,
element)
alpha_flux1_ip1 = (1 - alpha1[i + 1, j, element]) *
get_node_vars(antidiffusive_flux1, equations, dg, i + 1,
j, element)
alpha_flux2 = (1 - alpha2[i, j, element]) *
get_node_vars(antidiffusive_flux2, equations, dg, i, j,
element)
alpha_flux2_jp1 = (1 - alpha2[i, j + 1, element]) *
get_node_vars(antidiffusive_flux2, equations, dg, i,
j + 1, element)

for v in eachvariable(equations)
u[v, i, j, element] += dt * inverse_jacobian *
(inverse_weights[i] *
(alpha_flux1_ip1[v] - alpha_flux1[v]) +
inverse_weights[j] *
(alpha_flux2_jp1[v] - alpha_flux2[v]))
end
end
end

return nothing
end
end # @muladd
Loading