Skip to content

Commit 0dfa47b

Browse files
Add entropy stable LLF dissipation for the SWE (#132)
* add entropy stable LLF dissipation * fix comments * fix unit test
1 parent 33f9894 commit 0dfa47b

File tree

4 files changed

+130
-18
lines changed

4 files changed

+130
-18
lines changed

src/equations/shallow_water_2d.jl

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1130,7 +1130,9 @@ end
11301130
return SVector(f1, f2, f3, 0)
11311131
end
11321132

1133-
# Specialized `DissipationLocalLaxFriedrichs` to avoid spurious dissipation in the bottom topography
1133+
# Specialized `DissipationLocalLaxFriedrichs` to avoid spurious dissipation in the bottom topography.
1134+
# For discontinuous bottom topography [`Trixi.DissipationLaxFriedrichsEntropyVariables`](@extref)
1135+
# should be used instead as this version is not well-balanced.
11341136
@inline function (dissipation::DissipationLocalLaxFriedrichs)(u_ll, u_rr,
11351137
orientation_or_normal_direction,
11361138
equations::ShallowWaterEquations2D)
@@ -1140,6 +1142,35 @@ end
11401142
return SVector(diss[1], diss[2], diss[3], 0)
11411143
end
11421144

1145+
# Provably entropy stable and well-balanced local Lax-Friedrichs dissipation that avoids
1146+
# spurious dissipation in the bottom topography.
1147+
function (dissipation::DissipationLaxFriedrichsEntropyVariables)(u_ll, u_rr,
1148+
orientation_or_normal_direction,
1149+
equations::ShallowWaterEquations2D)
1150+
λ = dissipation.max_abs_speed(u_ll, u_rr, orientation_or_normal_direction,
1151+
equations)
1152+
g = equations.gravity
1153+
1154+
# Compute averages
1155+
h_avg = 0.5f0 * (u_ll[1] + u_rr[1])
1156+
v1_avg = 0.5f0 * (u_ll[2] / u_ll[1] + u_rr[2] / u_rr[1])
1157+
v2_avg = 0.5f0 * (u_ll[3] / u_ll[1] + u_rr[3] / u_rr[1])
1158+
1159+
# Compute the jump in entropy variables
1160+
w_ll = cons2entropy(u_ll, equations)
1161+
w_rr = cons2entropy(u_rr, equations)
1162+
w_jump = SVector{3}(w_rr[1] - w_ll[1], w_rr[2] - w_ll[2], w_rr[3] - w_ll[3])
1163+
1164+
# Compute the H := du/dw
1165+
H = 1 / g * @SMatrix [1 v1_avg v2_avg;
1166+
v1_avg g * h_avg+v1_avg^2 v1_avg*v2_avg;
1167+
v2_avg v1_avg*v2_avg g * h_avg+v2_avg^2]
1168+
1169+
diss = SVector(-0.5f0 * λ * H * w_jump)
1170+
1171+
return SVector(diss..., 0)
1172+
end
1173+
11431174
# Specialized `FluxHLL` to avoid spurious dissipation in the bottom topography
11441175
@inline function (numflux::FluxHLL)(u_ll, u_rr, orientation_or_normal_direction,
11451176
equations::ShallowWaterEquations2D)

src/equations/shallow_water_multilayer_2d.jl

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -993,7 +993,8 @@ Use in combination with the generic numerical flux routine [`FluxHydrostaticReco
993993
end
994994

995995
# Specialized `DissipationLocalLaxFriedrichs` to avoid spurious dissipation in the bottom
996-
# topography
996+
# topography. For discontinuous bottom topography [`Trixi.DissipationLaxFriedrichsEntropyVariables`](@extref)
997+
# should be used instead as this version is not well-balanced.
997998
@inline function (dissipation::DissipationLocalLaxFriedrichs)(u_ll, u_rr,
998999
orientation_or_normal_direction,
9991000
equations::ShallowWaterMultiLayerEquations2D)
@@ -1003,6 +1004,37 @@ end
10031004
return SVector(@views diss[1:(end - 1)]..., zero(eltype(u_ll)))
10041005
end
10051006

1007+
# Provably entropy stable and well-balanced local Lax-Friedrichs dissipation that avoids
1008+
# spurious dissipation in the bottom topography.
1009+
function (dissipation::DissipationLaxFriedrichsEntropyVariables)(u_ll, u_rr,
1010+
orientation_or_normal_direction,
1011+
equations::ShallowWaterMultiLayerEquations2D{4,
1012+
1,
1013+
T}) where {T}
1014+
λ = dissipation.max_abs_speed(u_ll, u_rr, orientation_or_normal_direction,
1015+
equations)
1016+
g = equations.gravity
1017+
1018+
# Compute averages
1019+
h_avg = 0.5f0 * (u_ll[1] + u_rr[1])
1020+
v1_avg = 0.5f0 * (u_ll[2] / u_ll[1] + u_rr[2] / u_rr[1])
1021+
v2_avg = 0.5f0 * (u_ll[3] / u_ll[1] + u_rr[3] / u_rr[1])
1022+
1023+
# Compute the jump in entropy variables
1024+
w_ll = cons2entropy(u_ll, equations)
1025+
w_rr = cons2entropy(u_rr, equations)
1026+
w_jump = SVector{3}(w_rr[1] - w_ll[1], w_rr[2] - w_ll[2], w_rr[3] - w_ll[3])
1027+
1028+
# Compute the H := du/dw
1029+
H = 1 / g * @SMatrix [1 v1_avg v2_avg;
1030+
v1_avg g * h_avg+v1_avg^2 v1_avg*v2_avg;
1031+
v2_avg v1_avg*v2_avg g * h_avg+v2_avg^2]
1032+
1033+
diss = SVector(-0.5f0 * λ * H * w_jump)
1034+
1035+
return SVector(diss..., 0)
1036+
end
1037+
10061038
@inline function Trixi.max_abs_speeds(u, equations::ShallowWaterMultiLayerEquations2D)
10071039
h = waterheight(u, equations)
10081040
h_v1, h_v2 = momentum(u, equations)

test/test_tree_2d.jl

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -288,6 +288,30 @@ isdir(outdir) && rm(outdir, recursive = true)
288288
@test_allocations(Trixi.rhs!, semi, sol, 1000)
289289
end
290290

291+
@trixi_testset "elixir_shallowwater_source_terms.jl with es-llf dissipation" begin
292+
@test_trixi_include(joinpath(EXAMPLES_DIR,
293+
"elixir_shallowwater_source_terms.jl"),
294+
l2=[
295+
0.0003733798777192089,
296+
0.02043287183047546,
297+
0.052383482460735806,
298+
6.274146767724067e-5
299+
],
300+
linf=[
301+
0.0022222461533480953,
302+
0.06863676418052789,
303+
0.13355361762228668,
304+
0.0001819675955490041
305+
],
306+
surface_flux=(FluxPlusDissipation(flux_fjordholm_etal,
307+
DissipationLaxFriedrichsEntropyVariables()),
308+
flux_nonconservative_fjordholm_etal),
309+
tspan=(0.0, 0.25))
310+
# Ensure that we do not have excessive memory allocations
311+
# (e.g., from type instabilities)
312+
@test_allocations(Trixi.rhs!, semi, sol, 1000)
313+
end
314+
291315
@trixi_testset "elixir_shallowwater_conical_island.jl" begin
292316
@test_trixi_include(joinpath(EXAMPLES_DIR,
293317
"elixir_shallowwater_conical_island.jl"),

test/test_unit.jl

Lines changed: 41 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -634,22 +634,6 @@ end
634634
end
635635
end
636636

637-
@timed_testset "Consistency check for SWME dissipation terms" begin
638-
# Test that for b=constant, the dissipation terms return the same output.
639-
equations = ShallowWaterMomentEquations1D(gravity = 9.81, n_moments = 2)
640-
equations_lin = ShallowWaterLinearizedMomentEquations1D(gravity = 9.81,
641-
n_moments = 2)
642-
u_ll = SVector(1.0, 0.3, 0.15, 0.15, 0.1)
643-
u_rr = SVector(1.5, 0.1, 0.25, 0.35, 0.1)
644-
645-
diss_lf = DissipationLocalLaxFriedrichs()
646-
diss_ec = DissipationLaxFriedrichsEntropyVariables()
647-
648-
@test diss_lf(u_ll, u_rr, 1, equations) diss_ec(u_ll, u_rr, 1, equations)
649-
@test diss_lf(u_ll, u_rr, 1, equations_lin)
650-
diss_ec(u_ll, u_rr, 1, equations_lin)
651-
end
652-
653637
# Check consistency for conservative two-point fluxes (f(u, u) = f(u))
654638
@timed_testset "Consistency check for SWME fluxes" begin
655639
equations = ShallowWaterMomentEquations1D(gravity = 9.81, n_moments = 2)
@@ -669,6 +653,47 @@ end
669653
@test poly 1
670654
@test deriv 0
671655
end
656+
657+
# Test that for b=constant, the dissipation terms return the same output.
658+
@testset "Consistency check for DissipationLaxFriedrichsEntropyVariables" begin
659+
@timed_testset "ShallowWaterEquations2D" begin
660+
equations = ShallowWaterEquations2D(gravity = 9.81)
661+
u_ll = SVector(1.0, 0.3, 0.2, 0.2)
662+
u_rr = SVector(1.5, 0.1, -0.1, 0.2)
663+
@test DissipationLaxFriedrichsEntropyVariables()(u_ll, u_rr, 1, equations)
664+
DissipationLocalLaxFriedrichs()(u_ll, u_rr, 1, equations)
665+
end
666+
667+
@timed_testset "ShalloWaterMultiLayerEquations2D (single layer)" begin
668+
equations = ShallowWaterMultiLayerEquations2D(gravity = 9.81, rhos = (1.0))
669+
u_ll = SVector(1.0, 0.3, 0.2, 0.1)
670+
u_rr = SVector(1.5, 0.1, -0.1, 0.1)
671+
@test DissipationLaxFriedrichsEntropyVariables()(u_ll, u_rr, 1, equations)
672+
DissipationLocalLaxFriedrichs()(u_ll, u_rr, 1, equations)
673+
674+
# For a single layer the dissipation should be consistent with the 2D SWE
675+
u_ll = SVector(1.0, 0.3, 0.2, 0.1)
676+
u_rr = SVector(1.5, 0.1, -0.1, 0.2)
677+
equations_swe = ShallowWaterEquations2D(gravity = 9.81)
678+
@test DissipationLaxFriedrichsEntropyVariables()(u_ll, u_rr, 1, equations)
679+
DissipationLaxFriedrichsEntropyVariables()(u_ll, u_rr, 1, equations_swe)
680+
end
681+
682+
@timed_testset "ShallowWaterMomentEquations1D" begin
683+
equations = ShallowWaterMomentEquations1D(gravity = 9.81, n_moments = 2)
684+
equations_lin = ShallowWaterLinearizedMomentEquations1D(gravity = 9.81,
685+
n_moments = 2)
686+
u_ll = SVector(1.0, 0.3, 0.15, 0.15, 0.1)
687+
u_rr = SVector(1.5, 0.1, 0.25, 0.35, 0.1)
688+
689+
diss_lf = DissipationLocalLaxFriedrichs()
690+
diss_ec = DissipationLaxFriedrichsEntropyVariables()
691+
692+
@test diss_lf(u_ll, u_rr, 1, equations) diss_ec(u_ll, u_rr, 1, equations)
693+
@test diss_lf(u_ll, u_rr, 1, equations_lin)
694+
diss_ec(u_ll, u_rr, 1, equations_lin)
695+
end
696+
end
672697
end # Unit tests
673698

674699
end # module

0 commit comments

Comments
 (0)