Skip to content

Commit

Permalink
Allow Fourier and periodic rational derivative operators for `BBMBBME…
Browse files Browse the repository at this point in the history
…quations1D` and `SvaerdKalischEquations1D` (#154)

* allow Fourier and periodic rational derivative operators

* format

* adjust tolerances

* avoid clutter

* fix

* add test for PeriodicRationalDerivativeOperator for BBMEquation1D
  • Loading branch information
JoshuaLampert authored Sep 24, 2024
1 parent 2f11fb1 commit a80b640
Show file tree
Hide file tree
Showing 13 changed files with 216 additions and 21 deletions.
2 changes: 1 addition & 1 deletion examples/bbm_1d/bbm_1d_basic.jl
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ semi = Semidiscretization(mesh, equations, initial_condition, solver,
tspan = (0.0, 1000.0)
ode = semidiscretize(semi, tspan)
summary_callback = SummaryCallback()
analysis_callback = AnalysisCallback(semi; interval = 10,
analysis_callback = AnalysisCallback(semi; interval = 100,
extra_analysis_errors = (:conservation_error,),
extra_analysis_integrals = (waterheight_total,
entropy_modified,
Expand Down
2 changes: 1 addition & 1 deletion examples/bbm_1d/bbm_1d_fourier.jl
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ semi = Semidiscretization(mesh, equations, initial_condition, solver,
tspan = (0.0, 1000.0)
ode = semidiscretize(semi, tspan)
summary_callback = SummaryCallback()
analysis_callback = AnalysisCallback(semi; interval = 10,
analysis_callback = AnalysisCallback(semi; interval = 100,
extra_analysis_errors = (:conservation_error,),
extra_analysis_integrals = (waterheight_total,
entropy_modified,
Expand Down
2 changes: 1 addition & 1 deletion examples/bbm_1d/bbm_1d_hamiltonian_relaxation.jl
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ semi = Semidiscretization(mesh, equations, initial_condition, solver,
tspan = (0.0, 1000.0)
ode = semidiscretize(semi, tspan)
summary_callback = SummaryCallback()
analysis_callback = AnalysisCallback(semi; interval = 10,
analysis_callback = AnalysisCallback(semi; interval = 100,
extra_analysis_errors = (:conservation_error,),
extra_analysis_integrals = (waterheight_total,
entropy_modified,
Expand Down
2 changes: 1 addition & 1 deletion examples/bbm_1d/bbm_1d_relaxation.jl
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ semi = Semidiscretization(mesh, equations, initial_condition, solver,
tspan = (0.0, 1000.0)
ode = semidiscretize(semi, tspan)
summary_callback = SummaryCallback()
analysis_callback = AnalysisCallback(semi; interval = 10,
analysis_callback = AnalysisCallback(semi; interval = 100,
extra_analysis_errors = (:conservation_error,),
extra_analysis_integrals = (waterheight_total,
entropy_modified,
Expand Down
43 changes: 43 additions & 0 deletions examples/bbm_bbm_1d/bbm_bbm_1d_fourier.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
using OrdinaryDiffEq
using DispersiveShallowWater
using SummationByPartsOperators: fourier_derivative_operator

###############################################################################
# Semidiscretization of the BBM-BBM equation

# or bathymetry_variable instead of bathymetry_flat
equations = BBMBBMEquations1D(bathymetry_type = bathymetry_flat, gravity_constant = 9.81)

# initial_condition_convergence_test needs periodic boundary conditions
initial_condition = initial_condition_convergence_test
boundary_conditions = boundary_condition_periodic

# create homogeneous mesh
coordinates_min = -35.0
coordinates_max = 35.0
N = 512
mesh = Mesh1D(coordinates_min, coordinates_max, N)

# create solver with Fourier SBP operators
D1 = fourier_derivative_operator(xmin(mesh), xmax(mesh), nnodes(mesh))
D2 = D1^2
solver = Solver(D1, D2)

# semidiscretization holds all the necessary data structures for the spatial discretization
semi = Semidiscretization(mesh, equations, initial_condition, solver,
boundary_conditions = boundary_conditions)

###############################################################################
# Create `ODEProblem` and run the simulation
tspan = (0.0, 30.0)
ode = semidiscretize(semi, tspan)
summary_callback = SummaryCallback()
analysis_callback = AnalysisCallback(semi; interval = 10,
extra_analysis_errors = (:conservation_error,),
extra_analysis_integrals = (waterheight_total,
velocity, entropy))
callbacks = CallbackSet(analysis_callback, summary_callback)

saveat = range(tspan..., length = 100)
sol = solve(ode, Tsit5(), abstol = 1e-7, reltol = 1e-7,
save_everystep = false, callback = callbacks, saveat = saveat)
43 changes: 43 additions & 0 deletions examples/svaerd_kalisch_1d/svaerd_kalisch_1d_dingemans_fourier.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
using OrdinaryDiffEq
using DispersiveShallowWater
using SummationByPartsOperators: fourier_derivative_operator

###############################################################################
# Semidiscretization of the Svärd-Kalisch equations

equations = SvaerdKalischEquations1D(gravity_constant = 9.81, eta0 = 0.8, alpha = 0.0,
beta = 0.27946992481203003, gamma = 0.0521077694235589)

initial_condition = initial_condition_dingemans
boundary_conditions = boundary_condition_periodic

# create homogeneous mesh
coordinates_min = -138.0
coordinates_max = 46.0
N = 512
mesh = Mesh1D(coordinates_min, coordinates_max, N)

# create solver with Fourier SBP operators
D1 = fourier_derivative_operator(xmin(mesh), xmax(mesh), nnodes(mesh))
D2 = D1^2
solver = Solver(D1, D2)

# semidiscretization holds all the necessary data structures for the spatial discretization
semi = Semidiscretization(mesh, equations, initial_condition, solver,
boundary_conditions = boundary_conditions)

###############################################################################
# Create `ODEProblem` and run the simulation
tspan = (0.0, 70.0)
ode = semidiscretize(semi, tspan)
summary_callback = SummaryCallback()
analysis_callback = AnalysisCallback(semi; interval = 10,
extra_analysis_errors = (:conservation_error,),
extra_analysis_integrals = (waterheight_total,
entropy,
entropy_modified))
callbacks = CallbackSet(analysis_callback, summary_callback)

saveat = range(tspan..., length = 500)
sol = solve(ode, Tsit5(), abstol = 1e-7, reltol = 1e-7,
save_everystep = false, callback = callbacks, saveat = saveat)
2 changes: 1 addition & 1 deletion src/equations/bbm_1d.jl
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,7 @@ function rhs!(dq, q, t, mesh, equations::BBMEquation1D, initial_condition,
@.. deta = -(0.75 * c_1 * eta2_x + c_0 * eta_x_upwind)
end
else
@error "unknown type of first-derivative operator: $(typeof(solver.D1))"
throw(ArgumentError("unknown type of first-derivative operator: $(typeof(solver.D1))"))
end
end

Expand Down
25 changes: 15 additions & 10 deletions src/equations/bbm_bbm_1d.jl
Original file line number Diff line number Diff line change
Expand Up @@ -299,13 +299,14 @@ function create_cache(mesh, equations::BBMBBMEquations1D,
end
K = Diagonal(D .^ 2)
if solver.D1 isa PeriodicDerivativeOperator ||
solver.D1 isa UniformPeriodicCoupledOperator
solver.D1 isa UniformPeriodicCoupledOperator ||
solver.D1 isa FourierDerivativeOperator
sparse_D1 = sparse(solver.D1)
invImDKD = lu(I - 1 / 6 * sparse_D1 * K * sparse_D1)
elseif solver.D1 isa PeriodicUpwindOperators
invImDKD = lu(I - 1 / 6 * sparse(solver.D1.minus) * K * sparse(solver.D1.plus))
else
@error "unknown type of first-derivative operator: $(typeof(solver.D1))"
throw(ArgumentError("unknown type of first-derivative operator: $(typeof(solver.D1))"))
end
invImD2K = lu(I - 1 / 6 * sparse(solver.D2) * K)

Expand Down Expand Up @@ -337,14 +338,15 @@ function create_cache(mesh, equations::BBMBBMEquations1D{BathymetryFlat},

# homogeneous Neumann boundary conditions
if solver.D1 isa DerivativeOperator ||
solver.D1 isa UniformCoupledOperator
solver.D1 isa UniformCoupledOperator ||
solver.D1 isa FourierDerivativeOperator
D1_b = BandedMatrix(solver.D1)
invImD2n = lu(I + 1 / 6 * D^2 * inv(M) * D1_b' * PdM * D1_b)
elseif solver.D1 isa UpwindOperators
D1plus_b = BandedMatrix(solver.D1.plus)
invImD2n = lu(I + 1 / 6 * D^2 * inv(M) * D1plus_b' * PdM * D1plus_b)
else
@error "unknown type of first-derivative operator: $(typeof(solver.D1))"
throw(ArgumentError("unknown type of first-derivative operator: $(typeof(solver.D1))"))
end

# create temporary storage
Expand Down Expand Up @@ -380,14 +382,15 @@ function create_cache(mesh, equations::BBMBBMEquations1D,

# homogeneous Neumann boundary conditions
if solver.D1 isa DerivativeOperator ||
solver.D1 isa UniformCoupledOperator
solver.D1 isa UniformCoupledOperator ||
solver.D1 isa FourierDerivativeOperator
D1_b = BandedMatrix(solver.D1)
invImD2n = lu(I + 1 / 6 * inv(M) * D1_b' * PdM * K * D1_b)
elseif solver.D1 isa UpwindOperators
D1plus_b = BandedMatrix(solver.D1.plus)
invImD2n = lu(I + 1 / 6 * inv(M) * D1plus_b' * PdM * K * D1plus_b)
else
@error "unknown type of first-derivative operator: $(typeof(solver.D1))"
throw(ArgumentError("unknown type of first-derivative operator: $(typeof(solver.D1))"))
end

# create temporary storage
Expand Down Expand Up @@ -431,7 +434,8 @@ function rhs!(dq, q, t, mesh, equations::BBMBBMEquations1D, initial_condition,
end
# energy and mass conservative semidiscretization
if solver.D1 isa PeriodicDerivativeOperator ||
solver.D1 isa UniformPeriodicCoupledOperator
solver.D1 isa UniformPeriodicCoupledOperator ||
solver.D1 isa FourierDerivativeOperator
@trixi_timeit timer() "deta hyperbolic" begin
mul!(deta, solver.D1, tmp1)
end
Expand All @@ -446,7 +450,7 @@ function rhs!(dq, q, t, mesh, equations::BBMBBMEquations1D, initial_condition,
mul!(dv, solver.D1.plus, tmp2)
end
else
@error "unknown type of first-derivative operator: $(typeof(solver.D1))"
throw(ArgumentError("unknown type of first-derivative operator: $(typeof(solver.D1))"))
end

@trixi_timeit timer() "source terms" calc_sources!(dq, q, t, source_terms, equations,
Expand Down Expand Up @@ -497,7 +501,8 @@ function rhs!(dq, q, t, mesh, equations::BBMBBMEquations1D, initial_condition,
end
# energy and mass conservative semidiscretization
if solver.D1 isa DerivativeOperator ||
solver.D1 isa UniformCoupledOperator
solver.D1 isa UniformCoupledOperator ||
solver.D1 isa FourierDerivativeOperator
@trixi_timeit timer() "deta hyperbolic" begin
mul!(deta, solver.D1, tmp1)
end
Expand All @@ -512,7 +517,7 @@ function rhs!(dq, q, t, mesh, equations::BBMBBMEquations1D, initial_condition,
mul!(dv, solver.D1.plus, tmp2)
end
else
@error "unknown type of first-derivative operator: $(typeof(solver.D1))"
throw(ArgumentError("unknown type of first-derivative operator: $(typeof(solver.D1))"))
end

@trixi_timeit timer() "source terms" calc_sources!(dq, q, t, source_terms, equations,
Expand Down
10 changes: 6 additions & 4 deletions src/equations/svaerd_kalisch_1d.jl
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,8 @@ function create_cache(mesh, equations::SvaerdKalischEquations1D,
M_beta = copy(beta_hat)
scale_by_mass_matrix!(M_beta, D1)
if D1 isa PeriodicDerivativeOperator ||
D1 isa UniformPeriodicCoupledOperator
D1 isa UniformPeriodicCoupledOperator ||
D1 isa FourierDerivativeOperator
D1_central = D1
D1mat = sparse(D1_central)
minus_MD1betaD1 = D1mat' * Diagonal(M_beta) * D1mat
Expand All @@ -195,7 +196,7 @@ function create_cache(mesh, equations::SvaerdKalischEquations1D,
D1, D1mat_minus, equations)
end
else
@error "unknown type of first-derivative operator: $(typeof(D1))"
throw(ArgumentError("unknown type of first-derivative operator: $(typeof(D1))"))
end
factorization = cholesky(system_matrix)
cache = (; factorization, minus_MD1betaD1, D, h, hv, b, eta_x, v_x,
Expand Down Expand Up @@ -251,7 +252,8 @@ function rhs!(dq, q, t, mesh, equations::SvaerdKalischEquations1D,
@.. hv = h * v

if D1 isa PeriodicDerivativeOperator ||
D1 isa UniformPeriodicCoupledOperator
D1 isa UniformPeriodicCoupledOperator ||
D1 isa FourierDerivativeOperator
mul!(eta_x, D1_central, eta)
mul!(v_x, D1_central, v)
@.. tmp1 = alpha_hat * eta_x
Expand Down Expand Up @@ -282,7 +284,7 @@ function rhs!(dq, q, t, mesh, equations::SvaerdKalischEquations1D,
mul!(deta, D1.minus, tmp1)
mul!(deta, D1_central, hv, -1.0, 1.0)
else
@error "unknown type of first derivative operator: $(typeof(D1))"
throw(ArgumentError("unknown type of first-derivative operator: $(typeof(D1))"))
end
end

Expand Down
3 changes: 2 additions & 1 deletion src/solver.jl
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ struct Solver{RealT <: Real,
}
@assert derivative_order(D1) == 1
if D2 isa AbstractDerivativeOperator &&
!(D2 isa SummationByPartsOperators.FourierPolynomialDerivativeOperator)
!(D2 isa SummationByPartsOperators.FourierPolynomialDerivativeOperator) &&
!(D2 isa SummationByPartsOperators.PeriodicRationalDerivativeOperator)
@assert derivative_order(D2) == 2
end
new(D1, D2)
Expand Down
17 changes: 17 additions & 0 deletions test/test_bbm_1d.jl
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,23 @@ end
end

@test_allocations(semi, sol, allocs=5_000)

# test PeriodicRationalDerivativeOperator
D1 = periodic_derivative_operator(1, accuracy_order, xmin(mesh), xmax(mesh),
nnodes(mesh))
D2 = D1^2
solver = Solver(D1, D2)
@test_trixi_include(joinpath(EXAMPLES_DIR, "bbm_1d_basic.jl"),
tspan=(0.0, 100.0),
solver=solver,
l2=[0.013447144236536044],
linf=[0.007184057857459125],
cons_error=[1.5543122344752192e-15],
change_waterheight=-1.5543122344752192e-15,
change_entropy_modified=-8.68871272874383e-7,
change_hamiltonian=-3.697687313897191e-6)

@test_allocations(semi, sol, allocs=5_000)
end

@testitem "bbm_1d_basic with split_form = false" setup=[
Expand Down
47 changes: 47 additions & 0 deletions test/test_bbm_bbm_1d.jl
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,24 @@ end
end

@test_allocations(semi, sol, allocs=10_000)

# test PeriodicRationalDerivativeOperator
D1 = periodic_derivative_operator(1, accuracy_order, xmin(mesh), xmax(mesh),
nnodes(mesh))
D2 = D1^2
solver = Solver(D1, D2)
@test_trixi_include(joinpath(EXAMPLES_DIR, "bbm_bbm_1d_basic.jl"),
tspan=(0.0, 1.0),
solver=solver,
l2=[0.0016951648276611925 0.0034269307395771303 0.0],
linf=[0.001453478820216958 0.001805665634286413 0.0],
cons_error=[2.055466838899258e-14 0.0 0.0],
change_waterheight=2.055466838899258e-14,
change_velocity=0.0,
change_entropy=0.00023833941781958856,
atol_ints=1e-10) # to make CI pass

@test_allocations(semi, sol, allocs=10_000)
end

@testitem "bbm_bbm_1d_basic with bathymetry_variable" setup=[Setup, BBMBBMEquation1D] begin
Expand Down Expand Up @@ -86,6 +104,35 @@ end
@test_allocations(semi, sol, allocs=10_000)
end

@testitem "bbm_bbm_1d_fourier" setup=[Setup, BBMBBMEquation1D] begin
@test_trixi_include(joinpath(EXAMPLES_DIR, "bbm_bbm_1d_fourier.jl"),
tspan=(0.0, 1.0),
l2=[7.291521968885259e-7 7.702204594455217e-7 0.0],
linf=[4.3579646391567195e-7 4.9442969896063e-7 0.0],
cons_error=[3.9206314028412105e-14 4.547473508864641e-13 0.0],
change_waterheight=3.9206314028412105e-14,
change_velocity=-4.547473508864641e-13,
change_entropy=0.0002383147650562023,
atol_ints=1e-10) # to make CI pass

@test_allocations(semi, sol, allocs=10_000)
end

@testitem "bbm_bbm_1d_fourier with bathymetry_variable" setup=[Setup, BBMBBMEquation1D] begin
@test_trixi_include(joinpath(EXAMPLES_DIR, "bbm_bbm_1d_fourier.jl"),
bathymetry_type=bathymetry_variable,
tspan=(0.0, 1.0),
l2=[7.291481123937497e-7 7.70214005540768e-7 0.0],
linf=[4.357912374297612e-7 4.94414834406598e-7 0.0],
cons_error=[6.232593470137382e-13 4.547473508864641e-13 0.0],
change_waterheight=6.232593470137382e-13,
change_velocity=-4.547473508864641e-13,
change_entropy=0.0002383154298968293,
atol_ints=1e-10) # to make CI pass

@test_allocations(semi, sol, allocs=10_000)
end

@testitem "bbm_bbm_1d_relaxation" setup=[Setup, BBMBBMEquation1D] begin
@test_trixi_include(joinpath(EXAMPLES_DIR, "bbm_bbm_1d_relaxation.jl"),
tspan=(0.0, 1.0),
Expand Down
Loading

0 comments on commit a80b640

Please sign in to comment.