Skip to content

Commit a7dcc23

Browse files
Add support for source terms (#65)
* add support for source terms * fix calculation of source terms * add test for manufactured solution of variable BBM-BBM * fix test of convergence order * adjust tolerance * source terms for BBMBBMEquations * format * WIP: add source terms for Svärd-Kalisch equations * Apply suggestions from code review Co-authored-by: Hendrik Ranocha <[email protected]> * add references * add support of source terms for Svärd-Kalisch equations with constant bathymetry * lower tolerances * fix tolerances * fix tolerances --------- Co-authored-by: Hendrik Ranocha <[email protected]>
1 parent 68e64f4 commit a7dcc23

13 files changed

+395
-65
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
using OrdinaryDiffEq
2+
using DispersiveShallowWater
3+
4+
###############################################################################
5+
# Semidiscretization of the BBM-BBM equations
6+
7+
equations = BBMBBMEquations1D(gravity_constant = 9.81, D = 4.0)
8+
9+
initial_condition = initial_condition_manufactured
10+
source_terms = source_terms_manufactured
11+
boundary_conditions = boundary_condition_periodic
12+
13+
# create homogeneous mesh
14+
coordinates_min = 0.0
15+
coordinates_max = 1.0
16+
N = 512
17+
mesh = Mesh1D(coordinates_min, coordinates_max, N)
18+
19+
# create solver with periodic SBP operators of accuracy order 4
20+
accuracy_order = 4
21+
solver = Solver(mesh, accuracy_order)
22+
23+
# semidiscretization holds all the necessary data structures for the spatial discretization
24+
semi = Semidiscretization(mesh, equations, initial_condition, solver,
25+
boundary_conditions = boundary_conditions,
26+
source_terms = source_terms)
27+
28+
###############################################################################
29+
# Create `ODEProblem` and run the simulation
30+
tspan = (0.0, 1.0)
31+
ode = semidiscretize(semi, tspan)
32+
analysis_callback = AnalysisCallback(semi; interval = 10,
33+
extra_analysis_errors = (:conservation_error,),
34+
extra_analysis_integrals = (waterheight_total,
35+
velocity, entropy))
36+
callbacks = CallbackSet(analysis_callback)
37+
38+
saveat = range(tspan..., length = 100)
39+
sol = solve(ode, Tsit5(), abstol = 1e-7, reltol = 1e-7,
40+
save_everystep = false, callback = callbacks, saveat = saveat)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
using OrdinaryDiffEq
2+
using DispersiveShallowWater
3+
4+
###############################################################################
5+
# Semidiscretization of the BBM-BBM equations
6+
7+
equations = BBMBBMVariableEquations1D(gravity_constant = 9.81)
8+
9+
initial_condition = initial_condition_manufactured
10+
source_terms = source_terms_manufactured
11+
boundary_conditions = boundary_condition_periodic
12+
13+
# create homogeneous mesh
14+
coordinates_min = 0.0
15+
coordinates_max = 1.0
16+
N = 512
17+
mesh = Mesh1D(coordinates_min, coordinates_max, N)
18+
19+
# create solver with periodic SBP operators of accuracy order 4
20+
accuracy_order = 4
21+
solver = Solver(mesh, accuracy_order)
22+
23+
# semidiscretization holds all the necessary data structures for the spatial discretization
24+
semi = Semidiscretization(mesh, equations, initial_condition, solver,
25+
boundary_conditions = boundary_conditions,
26+
source_terms = source_terms)
27+
28+
###############################################################################
29+
# Create `ODEProblem` and run the simulation
30+
tspan = (0.0, 1.0)
31+
ode = semidiscretize(semi, tspan)
32+
analysis_callback = AnalysisCallback(semi; interval = 10,
33+
extra_analysis_errors = (:conservation_error,),
34+
extra_analysis_integrals = (waterheight_total,
35+
velocity, entropy))
36+
callbacks = CallbackSet(analysis_callback)
37+
38+
saveat = range(tspan..., length = 100)
39+
sol = solve(ode, Tsit5(), abstol = 1e-7, reltol = 1e-7,
40+
save_everystep = false, callback = callbacks, saveat = saveat)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
using OrdinaryDiffEq
2+
using DispersiveShallowWater
3+
4+
###############################################################################
5+
# Semidiscretization of the Svärd-Kalisch equations
6+
7+
equations = SvaerdKalischEquations1D(gravity_constant = 1.0, eta0 = 0.0,
8+
alpha = 0.0004040404040404049,
9+
beta = 0.49292929292929294,
10+
gamma = 0.15707070707070708)
11+
12+
initial_condition = initial_condition_manufactured
13+
source_terms = source_terms_manufactured
14+
boundary_conditions = boundary_condition_periodic
15+
16+
# create homogeneous mesh
17+
coordinates_min = 0.0
18+
coordinates_max = 1.0
19+
N = 128
20+
mesh = Mesh1D(coordinates_min, coordinates_max, N)
21+
22+
# create solver with periodic SBP operators of accuracy order 4
23+
accuracy_order = 4
24+
solver = Solver(mesh, accuracy_order)
25+
26+
# semidiscretization holds all the necessary data structures for the spatial discretization
27+
semi = Semidiscretization(mesh, equations, initial_condition, solver,
28+
boundary_conditions = boundary_conditions,
29+
source_terms = source_terms)
30+
31+
###############################################################################
32+
# Create `ODEProblem` and run the simulation
33+
tspan = (0.0, 1.0)
34+
ode = semidiscretize(semi, tspan)
35+
analysis_callback = AnalysisCallback(semi; interval = 10,
36+
extra_analysis_errors = (:conservation_error,),
37+
extra_analysis_integrals = (waterheight_total,
38+
velocity, entropy))
39+
callbacks = CallbackSet(analysis_callback)
40+
41+
saveat = range(tspan..., length = 100)
42+
sol = solve(ode, Tsit5(), abstol = 1e-7, reltol = 1e-7,
43+
save_everystep = false, callback = callbacks, saveat = saveat)

src/DispersiveShallowWater.jl

+4-2
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@ import SummationByPartsOperators: grid, xmin, xmax
2323

2424
include("boundary_conditions.jl")
2525
include("mesh.jl")
26-
include("solver.jl")
2726
include("equations/equations.jl")
27+
include("solver.jl")
2828
include("semidiscretization.jl")
2929
include("callbacks_step/callbacks_step.jl")
3030
include("visualization.jl")
@@ -47,7 +47,9 @@ export Semidiscretization, semidiscretize, grid
4747

4848
export boundary_condition_periodic
4949

50-
export initial_condition_convergence_test, initial_condition_dingemans
50+
export initial_condition_convergence_test,
51+
initial_condition_manufactured, source_terms_manufactured,
52+
initial_condition_dingemans
5153

5254
export AnalysisCallback, RelaxationCallback
5355
export tstops, errors, integrals

src/equations/bbm_bbm_1d.jl

+55-11
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,41 @@ function initial_condition_convergence_test(x, t, equations::BBMBBMEquations1D,
5353
return SVector(eta, v)
5454
end
5555

56+
"""
57+
initial_condition_manufactured(x, t, equations::BBMBBMEquations1D, mesh)
58+
59+
A smooth manufactured solution in combination with [`source_terms_manufactured`](@ref).
60+
"""
61+
function initial_condition_manufactured(x, t,
62+
equations::BBMBBMEquations1D,
63+
mesh)
64+
eta = exp(t) * cospi(2 * (x - 2 * t))
65+
v = exp(t / 2) * sinpi(2 * (x - t / 2))
66+
return SVector(eta, v)
67+
end
68+
69+
"""
70+
source_terms_manufactured(q, x, t, equations::BBMBBMEquations1D, mesh)
71+
72+
A smooth manufactured solution in combination with [`initial_condition_manufactured`](@ref).
73+
"""
74+
function source_terms_manufactured(q, x, t, equations::BBMBBMEquations1D)
75+
g = equations.gravity
76+
D = equations.D
77+
a3 = cospi(t - 2 * x)
78+
a4 = sinpi(t - 2 * x)
79+
a5 = sinpi(2 * t - 4 * x)
80+
a6 = sinpi(4 * t - 2 * x)
81+
a7 = cospi(4 * t - 2 * x)
82+
dq1 = -2 * pi^2 * D^2 * (4 * pi * a6 - a7) * exp(t) / 3 + 2 * pi * D * exp(t / 2) * a3 -
83+
2 * pi * exp(3 * t / 2) * a4 * a6 + 2 * pi * exp(3 * t / 2) * a3 * a7 -
84+
4 * pi * exp(t) * a6 + exp(t) * a7
85+
dq2 = -pi^2 * D^2 * (a4 + 2 * pi * a3) * exp(t / 2) / 3 + 2 * pi * g * exp(t) * a6 -
86+
exp(t / 2) * a4 / 2 - pi * exp(t / 2) * a3 - pi * exp(t) * a5
87+
88+
return SVector(dq1, dq2)
89+
end
90+
#
5691
function create_cache(mesh,
5792
equations::BBMBBMEquations1D,
5893
solver,
@@ -61,24 +96,23 @@ function create_cache(mesh,
6196
uEltype)
6297
if solver.D1 isa PeriodicDerivativeOperator ||
6398
solver.D1 isa UniformPeriodicCoupledOperator
64-
invImD2_D = (I - 1 / 6 * equations.D^2 * sparse(solver.D2)) \ Matrix(solver.D1)
99+
invImD2 = inv(I - 1 / 6 * equations.D^2 * Matrix(solver.D2))
65100
elseif solver.D1 isa PeriodicUpwindOperators
66-
invImD2_D = (I - 1 / 6 * equations.D^2 * sparse(solver.D2)) \
67-
Matrix(solver.D1.central)
101+
invImD2 = inv(I - 1 / 6 * equations.D^2 * Matrix(solver.D2))
68102
else
69103
@error "unknown type of first-derivative operator"
70104
end
71-
tmp1 = Array{RealT}(undef, nnodes(mesh))
72-
return (invImD2_D = invImD2_D, tmp1 = tmp1)
105+
tmp1 = Array{RealT}(undef, nnodes(mesh)) # tmp1 is needed for the `RelaxationCallback`
106+
return (invImD2 = invImD2, tmp1 = tmp1)
73107
end
74108

75109
# Discretization that conserves the mass (for eta and v) and the energy for periodic boundary conditions, see
76110
# - Hendrik Ranocha, Dimitrios Mitsotakis and David I. Ketcheson (2020)
77111
# A Broad Class of Conservative Numerical Methods for Dispersive Wave Equations
78112
# [DOI: 10.4208/cicp.OA-2020-0119](https://doi.org/10.4208/cicp.OA-2020-0119)
79113
function rhs!(du_ode, u_ode, t, mesh, equations::BBMBBMEquations1D, initial_condition,
80-
::BoundaryConditionPeriodic, solver, cache)
81-
@unpack invImD2_D, tmp1 = cache
114+
::BoundaryConditionPeriodic, source_terms, solver, cache)
115+
@unpack invImD2 = cache
82116

83117
q = wrap_array(u_ode, mesh, equations, solver)
84118
dq = wrap_array(du_ode, mesh, equations, solver)
@@ -89,11 +123,21 @@ function rhs!(du_ode, u_ode, t, mesh, equations::BBMBBMEquations1D, initial_cond
89123
dv = view(dq, 2, :)
90124

91125
# energy and mass conservative semidiscretization
92-
@. tmp1 = -(equations.D * v + eta * v)
93-
mul!(deta, invImD2_D, tmp1)
126+
if solver.D1 isa PeriodicDerivativeOperator ||
127+
solver.D1 isa UniformPeriodicCoupledOperator
128+
deta[:] = -solver.D1 * (equations.D * v + eta .* v)
129+
dv[:] = -solver.D1 * (equations.gravity * eta + 0.5 * v .^ 2)
130+
elseif solver.D1 isa PeriodicUpwindOperators
131+
deta[:] = -solver.D1.central * (equations.D * v + eta .* v)
132+
dv[:] = -solver.D1.central * (equations.gravity * eta + 0.5 * v .^ 2)
133+
else
134+
@error "unknown type of first-derivative operator"
135+
end
136+
137+
calc_sources!(dq, q, t, source_terms, equations, solver)
94138

95-
@. tmp1 = -(equations.gravity * eta + 0.5 * v^2)
96-
mul!(dv, invImD2_D, tmp1)
139+
deta[:] = invImD2 * deta
140+
dv[:] = invImD2 * dv
97141

98142
return nothing
99143
end

src/equations/bbm_bbm_variable_bathymetry_1d.jl

+68-18
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,7 @@ For details see Example 5 in Section 3 from (here adapted for dimensional equati
4141
Exact Traveling-Wave Solutions to Bidirectional Wave Equations
4242
[DOI: 10.1023/A:1026667903256](https://doi.org/10.1023/A:1026667903256)
4343
"""
44-
function initial_condition_convergence_test(x,
45-
t,
44+
function initial_condition_convergence_test(x, t,
4645
equations::BBMBBMVariableEquations1D,
4746
mesh)
4847
g = equations.gravity
@@ -58,6 +57,49 @@ function initial_condition_convergence_test(x,
5857
return SVector(eta, v, D)
5958
end
6059

60+
"""
61+
initial_condition_manufactured(x, t, equations::BBMBBMVariableEquations1D, mesh)
62+
63+
A smooth manufactured solution in combination with [`source_terms_manufactured`](@ref).
64+
"""
65+
function initial_condition_manufactured(x, t,
66+
equations::BBMBBMVariableEquations1D,
67+
mesh)
68+
eta = exp(t) * cospi(2 * (x - 2 * t))
69+
v = exp(t / 2) * sinpi(2 * (x - t / 2))
70+
D = 5.0 + 2.0 * cospi(2 * x)
71+
return SVector(eta, v, D)
72+
end
73+
74+
"""
75+
source_terms_manufactured(q, x, t, equations::BBMBBMVariableEquations1D, mesh)
76+
77+
A smooth manufactured solution in combination with [`initial_condition_manufactured`](@ref).
78+
"""
79+
function source_terms_manufactured(q, x, t, equations::BBMBBMVariableEquations1D)
80+
g = equations.gravity
81+
a1 = cospi(2 * x)
82+
a2 = sinpi(2 * x)
83+
a3 = cospi(t - 2 * x)
84+
a4 = sinpi(t - 2 * x)
85+
a5 = sinpi(2 * t - 4 * x)
86+
a6 = sinpi(4 * t - 2 * x)
87+
a7 = cospi(4 * t - 2 * x)
88+
dq1 = -2 * pi^2 * (4 * pi * a6 - a7) * (2 * a1 + 5)^2 * exp(t) / 3 +
89+
8 * pi^2 * (a6 + 4 * pi * a7) * (2 * a1 + 5) * exp(t) * a2 / 3 +
90+
2 * pi * (2 * a1 + 5) * exp(t / 2) * a3 - 2 * pi * exp(3 * t / 2) * a4 * a6 +
91+
2 * pi * exp(3 * t / 2) * a3 * a7 + 4 * pi * exp(t / 2) * a2 * a4 -
92+
4 * pi * exp(t) * a6 + exp(t) * a7
93+
dq2 = 2 * pi * g * exp(t) * a6 -
94+
pi^2 *
95+
(8 * (2 * pi * a4 - a3) * (2 * a1 + 5) * a2 +
96+
(a4 + 2 * pi * a3) * (2 * a1 + 5)^2 +
97+
4 * (a4 + 2 * pi * a3) * (16 * sinpi(x)^4 - 26 * sinpi(x)^2 + 7)) * exp(t / 2) /
98+
3 - exp(t / 2) * a4 / 2 - pi * exp(t / 2) * a3 - pi * exp(t) * a5
99+
100+
return SVector(dq1, dq2, 0.0)
101+
end
102+
61103
"""
62104
initial_condition_dingemans(x, t, equations::BBMBBMVariableEquations1D, mesh)
63105
@@ -100,7 +142,7 @@ end
100142

101143
function create_cache(mesh,
102144
equations::BBMBBMVariableEquations1D,
103-
solver::Solver,
145+
solver,
104146
initial_condition,
105147
RealT,
106148
uEltype)
@@ -113,18 +155,16 @@ function create_cache(mesh,
113155
K = Diagonal(D .^ 2)
114156
if solver.D1 isa PeriodicDerivativeOperator ||
115157
solver.D1 isa UniformPeriodicCoupledOperator
116-
invImDKD_D = (I - 1 / 6 * sparse(solver.D1) * K * sparse(solver.D1)) \
117-
Matrix(solver.D1)
118-
invImD2K_D = (I - 1 / 6 * sparse(solver.D2) * K) \ Matrix(solver.D1)
158+
invImDKD = inv(I - 1 / 6 * Matrix(solver.D1) * K * Matrix(solver.D1))
159+
invImD2K = inv(I - 1 / 6 * Matrix(solver.D2) * K)
119160
elseif solver.D1 isa PeriodicUpwindOperators
120-
invImDKD_D = (I - 1 / 6 * sparse(solver.D1.minus) * K * sparse(solver.D1.plus)) \
121-
Matrix(solver.D1.minus)
122-
invImD2K_D = (I - 1 / 6 * sparse(solver.D2) * K) \ Matrix(solver.D1.plus)
161+
invImDKD = inv(I - 1 / 6 * Matrix(solver.D1.minus) * K * Matrix(solver.D1.plus))
162+
invImD2K = inv(I - 1 / 6 * Matrix(solver.D2) * K)
123163
else
124164
@error "unknown type of first-derivative operator"
125165
end
126-
tmp1 = Array{RealT}(undef, nnodes(mesh))
127-
return (invImDKD_D = invImDKD_D, invImD2K_D = invImD2K_D, tmp1 = tmp1)
166+
tmp1 = Array{RealT}(undef, nnodes(mesh)) # tmp1 is needed for the `RelaxationCallback`
167+
return (invImDKD = invImDKD, invImD2K = invImD2K, tmp1 = tmp1)
128168
end
129169

130170
# Discretization that conserves the mass (for eta and v) and the energy for periodic boundary conditions, see
@@ -133,9 +173,9 @@ end
133173
# [DOI: 10.4208/cicp.OA-2020-0119](https://doi.org/10.4208/cicp.OA-2020-0119)
134174
# Here, adapted for spatially varying bathymetry.
135175
function rhs!(du_ode, u_ode, t, mesh, equations::BBMBBMVariableEquations1D,
136-
initial_condition,
137-
::BoundaryConditionPeriodic, solver, cache)
138-
@unpack invImDKD_D, invImD2K_D, tmp1 = cache
176+
initial_condition, ::BoundaryConditionPeriodic, source_terms,
177+
solver, cache)
178+
@unpack invImDKD, invImD2K = cache
139179

140180
q = wrap_array(u_ode, mesh, equations, solver)
141181
dq = wrap_array(du_ode, mesh, equations, solver)
@@ -148,11 +188,21 @@ function rhs!(du_ode, u_ode, t, mesh, equations::BBMBBMVariableEquations1D,
148188
dD = view(dq, 3, :)
149189
fill!(dD, zero(eltype(dD)))
150190

151-
@. tmp1 = -(D * v + eta * v)
152-
mul!(deta, invImDKD_D, tmp1)
191+
if solver.D1 isa PeriodicDerivativeOperator ||
192+
solver.D1 isa UniformPeriodicCoupledOperator
193+
deta[:] = -solver.D1 * (D .* v + eta .* v)
194+
dv[:] = -solver.D1 * (equations.gravity * eta + 0.5 * v .^ 2)
195+
elseif solver.D1 isa PeriodicUpwindOperators
196+
deta[:] = -solver.D1.minus * (D .* v + eta .* v)
197+
dv[:] = -solver.D1.plus * (equations.gravity * eta + 0.5 * v .^ 2)
198+
else
199+
@error "unknown type of first-derivative operator"
200+
end
201+
202+
calc_sources!(dq, q, t, source_terms, equations, solver)
153203

154-
@. tmp1 = -(equations.gravity * eta + 0.5 * v^2)
155-
mul!(dv, invImD2K_D, tmp1)
204+
deta[:] = invImDKD * deta
205+
dv[:] = invImD2K * dv
156206

157207
return nothing
158208
end

0 commit comments

Comments
 (0)