Skip to content
This repository was archived by the owner on Jul 19, 2023. It is now read-only.

Commit bb0d379

Browse files
Merge pull request #346 from mjsheikh/tutorial
Tutorial
2 parents cd9bb90 + 1ce8503 commit bb0d379

3 files changed

Lines changed: 67 additions & 9 deletions

File tree

docs/make.jl

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@ makedocs(
1515
"Symbolic Tutorials" => [
1616
"symbolic_tutorials/mol_heat.md"
1717
],
18+
"Operator Tutorials" => [
19+
"operator_tutorials/kdv.md"
20+
],
1821
"Operators" => [
1922
"operators/operator_overview.md",
2023
"operators/derivative_operators.md",
@@ -26,8 +29,8 @@ makedocs(
2629
],
2730
"Nonlinear Derivatives" => [
2831
"nonlinear_derivatives/nonlinear_diffusion.md"
29-
]
30-
]
32+
]
33+
]
3134
)
3235

3336
deploydocs(

docs/src/operator_tutorials/kdv.md

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
# Solving KdV Solitons with Upwinding Operators
2+
3+
The KdV equation is of the form `uₜ + αuuₓ + βuₓₓₓ = 0`. Here we'll use `α = 6`, `β = 1` for
4+
simplicity of the true solution expression.
5+
6+
### 1-Soliton solution using Upwind Difference
7+
8+
The analytical expression for the single soliton case takes the form `u(x,t) = (c/2)/cosh²(√c * ξ/2)`.
9+
10+
`c > 0` (wave speed) ; `ξ = x - c*t` (moving coordinate)
11+
12+
```julia
13+
using Test
14+
using DiffEqOperators, OrdinaryDiffEq, LinearAlgebra
15+
16+
# Space domain and grids
17+
N = 21
18+
Δx = 1/(N-1)
19+
c = 1
20+
x = -10:Δx:10;
21+
22+
# solution of the single forward moving wave
23+
ϕ(x,t) = (1/2)*sech.((x .- t)/2).^2
24+
25+
# Discretizing the PDE at t = 0
26+
u0 = ϕ(x,0);
27+
du = zeros(size(x));
28+
29+
# Declaring the Upwind operator with winding = -1 since the wave travels from left to right
30+
A = UpwindDifference{Float64}(1,3,Δx,length(x),-1);
31+
32+
# Defining the ODE problem
33+
function KdV(du, u, p, t)
34+
bc = GeneralBC([0,1,-6*ϕ(-10,t),0,-1],[0,1,-6*ϕ(10,t),0,-1],Δx,3)
35+
mul!(du,A,bc*u)
36+
end
37+
38+
single_solition = ODEProblem(KdV, u0, (0.,5.));
39+
40+
# Solving the ODE problem
41+
soln = solve(single_solition,Tsit5(),abstol=1e-6,reltol=1e-6);
42+
43+
# Plotting the results, comparing Analytical and Numerical solutions
44+
using Plots
45+
plot(ϕ(x,0), title = "Single forward moving wave", yaxis="u(x,t)", label = "t = 0.0 (Analytic)")
46+
plot!(ϕ(x,2), label = "t = 2.0 (Analytic)")
47+
plot!(soln(0.0), label = "t = 0.0 (Numerical)",ls = :dash)
48+
plot!(soln(2.0), label = "t = 2.0 (Numerical)",ls = :dash)
49+
```
50+
![solution_plot](https://user-images.githubusercontent.com/39168576/111033316-a702a180-8436-11eb-9b8e-749ad9206639.jpeg)

src/derivative_operators/derivative_operator.jl

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -26,34 +26,37 @@ struct DerivativeOperator{T<:Real,N,Wind,T2,S1,S2<:SArray,T3,F} <: AbstractDeriv
2626
coeff_func :: F
2727
end
2828

29-
function nonlinear_diffusion!(du::AbstractVector{T}, second_differential_order::Int, first_differential_order::Int, approx_order::Int,
29+
struct nonlinear_diffusion!{N} end
30+
struct nonlinear_diffusion{N} end
31+
32+
function nonlinear_diffusion!{N}(du::AbstractVector{T}, second_differential_order::Int, first_differential_order::Int, approx_order::Int,
3033
p::AbstractVector{T}, q::AbstractVector{T}, dx::Union{T , AbstractVector{T} , Real},
3134
nknots::Int) where {T<:Real, N}
3235
#q is given by bc*u , u being the unknown function
3336
#p is given as some function of q , p being the diffusion coefficient
3437

3538
@assert approx_order>1 "approximation_order must be greater than 1."
3639
if first_differential_order > 0
37-
du .= (CenteredDifference(first_differential_order,approx_order,dx,nknots)*q).*(CenteredDifference(second_differential_order,approx_order,dx,nknots)*p)
40+
du .= (CenteredDifference{N}(first_differential_order,approx_order,dx,nknots)*q).*(CenteredDifference{N}(second_differential_order,approx_order,dx,nknots)*p)
3841
else
39-
du .= q[2:(nknots + 1)].*(CenteredDifference(second_differential_order,approx_order,dx,nknots)*p)
42+
du .= q[2:(nknots + 1)].*(CenteredDifference{N}(second_differential_order,approx_order,dx,nknots)*p)
4043
end
4144

4245
for l = 1:(second_differential_order - 1)
43-
du .= du .+ binomial(second_differential_order,l)*(CenteredDifference(l + first_differential_order,approx_order,dx,nknots)*q).*(CenteredDifference(second_differential_order - l,approx_order,dx,nknots)*p)
46+
du .= du .+ binomial(second_differential_order,l)*(CenteredDifference{N}(l + first_differential_order,approx_order,dx,nknots)*q).*(CenteredDifference{N}(second_differential_order - l,approx_order,dx,nknots)*p)
4447
end
4548

46-
du .= du .+ (CenteredDifference(first_differential_order + second_differential_order,approx_order,dx,nknots)*q).*p[2:(nknots + 1)]
49+
du .= du .+ (CenteredDifference{N}(first_differential_order + second_differential_order,approx_order,dx,nknots)*q).*p[2:(nknots + 1)]
4750

4851
end
4952

5053
# An out of place workaround for the mutating version
51-
function nonlinear_diffusion(second_differential_order::Int, first_differential_order::Int, approx_order::Int,
54+
function nonlinear_diffusion{N}(second_differential_order::Int, first_differential_order::Int, approx_order::Int,
5255
p::AbstractVector{T}, q::AbstractVector{T}, dx::Union{T , AbstractVector{T} , Real},
5356
nknots::Int) where {T<:Real, N}
5457

5558
du = similar(q,length(q) - 2)
56-
return nonlinear_diffusion!(du,second_differential_order,first_differential_order,approx_order,p,q,dx,nknots)
59+
return nonlinear_diffusion!{N}(du,second_differential_order,first_differential_order,approx_order,p,q,dx,nknots)
5760
end
5861

5962
struct CenteredDifference{N} end
@@ -264,6 +267,8 @@ end
264267

265268
CenteredDifference(args...) = CenteredDifference{1}(args...)
266269
UpwindDifference(args...) = UpwindDifference{1}(args...)
270+
nonlinear_diffusion(args...) = nonlinear_diffusion{1}(args...)
271+
nonlinear_diffusion!(args...) = nonlinear_diffusion!{1}(args...)
267272
use_winding(A::DerivativeOperator{T,N,Wind}) where {T,N,Wind} = Wind
268273
diff_axis(A::DerivativeOperator{T,N}) where {T,N} = N
269274
function ==(A1::DerivativeOperator, A2::DerivativeOperator)

0 commit comments

Comments
 (0)