Skip to content

Commit 6891e37

Browse files
committed
Correct first derivatives for non-uniform StaggeredFiniteDifferences
1 parent 441c3aa commit 6891e37

File tree

3 files changed

+45
-21
lines changed

3 files changed

+45
-21
lines changed

src/fd_derivatives.jl

Lines changed: 25 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,43 @@
11
# * Derivatives
22
# ** Three-point stencils
3+
4+
# α = super-/subdiagonal of second derivative
5+
# β = -1/2 diagonal of second derivative
6+
# γ = diagonal of first derivative
7+
# δ = super-/subdiagonal of first derivative
8+
39
α(::FiniteDifferences{T}, ::Integer) where T = one(T)
410
β(::FiniteDifferences{T}, ::Integer) where T = one(T)
511
γ(::FiniteDifferences{T}, ::Integer) where T = zero(T)
12+
δ(::FiniteDifferences{T}, ::Integer) where T = one(T)
613

714
α(B::StaggeredFiniteDifferences, j::Integer) = B.α[j]
8-
β(B::StaggeredFiniteDifferences{T}, j::Integer) where T = B.β[j]
15+
β(B::StaggeredFiniteDifferences, j::Integer) = B.β[j]
916
γ( ::StaggeredFiniteDifferences{T}, ::Integer) where T = zero(T)
17+
δ(B::StaggeredFiniteDifferences, j::Integer) = B.δ[j]
1018

11-
α(B::StaggeredFiniteDifferences) = B.α
12-
β(B::StaggeredFiniteDifferences) = B.β
19+
α(B::StaggeredFiniteDifferences) = B.α
20+
β(B::StaggeredFiniteDifferences) = B.β
1321
γ(B::StaggeredFiniteDifferences{T}) where T = zeros(T, length(B.r))
22+
δ(B::StaggeredFiniteDifferences) = B.δ
1423

1524
α( ::ImplicitFiniteDifferences{T}, ::Integer) where T = one(T)
1625
β(B::ImplicitFiniteDifferences{T}, j::Integer) where T = one(T) + (j == 1 ? B.δβ₁ : zero(T))
1726
γ(B::ImplicitFiniteDifferences{T}, j::Integer) where T = (j == 1 ? B.λ : zero(T))
27+
δ( ::ImplicitFiniteDifferences{T}, ::Integer) where T = one(T)
1828

1929
α(B::AbstractFiniteDifferences) = α.(Ref(B), B.j[1:end-1])
2030
β(B::AbstractFiniteDifferences) = β.(Ref(B), B.j)
2131
γ(B::AbstractFiniteDifferences) = γ.(Ref(B), B.j)
32+
δ(B::AbstractFiniteDifferences) = δ.(Ref(B), B.j[1:end-1])
2233

23-
function α(B̃::RestrictedFiniteDifferences)
24-
j = indices(B̃,2)
25-
α(parent(B̃))[j[1]:(j[end]-1)]
34+
for f in [, ]
35+
@eval begin
36+
function $f(B̃::RestrictedFiniteDifferences)
37+
j = indices(B̃,2)
38+
$f(parent(B̃))[j[1]:(j[end]-1)]
39+
end
40+
end
2641
end
2742

2843
for f in [, ]
@@ -33,7 +48,7 @@ for f in [:β, :γ]
3348
end
3449
end
3550

36-
for f in [, , ]
51+
for f in [, , , ]
3752
@eval begin
3853
function $f(Ã::BasisOrRestricted{<:AbstractFiniteDifferences},
3954
::BasisOrRestricted{<:AbstractFiniteDifferences},
@@ -84,10 +99,10 @@ end
8499

85100
# Central difference approximation
86101
μ = 2step(B)
87-
a = α(B)/μ
88-
dest.dl .= -a
102+
d = δ(B)/μ
103+
dest.dl .= -d
89104
dest.d .= γ(B)/μ
90-
dest.du .= a
105+
dest.du .= d
91106
end
92107
dest::BandedMatrix{T} -> begin
93108
A = parent(Ac)

src/finite_differences.jl

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -242,13 +242,15 @@ r = 0. Supports non-uniform grids, c.f.
242242
10118–10125. http://dx.doi.org/10.1021/jp992144
243243
244244
"""
245-
struct StaggeredFiniteDifferences{T,V<:AbstractVector{T},A,B} <: AbstractFiniteDifferences{T,Int}
245+
struct StaggeredFiniteDifferences{T,V<:AbstractVector{T},A,B,D} <: AbstractFiniteDifferences{T,Int}
246246
r::V
247247
Z::T
248248
δβ₁::T # Correction used for bare Coulomb potentials, Eq. (22) Schafer2009
249249
α::A
250250
β::B
251+
δ::D
251252

253+
# Uniform case
252254
function StaggeredFiniteDifferences(r::V, Z=one(T),
253255
δβ₁=schafer_corner_fix(local_step(r,1), Z)) where {T,V<:AbstractRange{T}}
254256
issorted(r) ||
@@ -263,9 +265,10 @@ struct StaggeredFiniteDifferences{T,V<:AbstractVector{T},A,B} <: AbstractFiniteD
263265

264266
β[1] += δβ₁ * step(r)^2
265267

266-
new{T,V,typeof(α),typeof(β)}(r, T(Z), T(δβ₁), α, β)
268+
new{T,V,typeof(α),typeof(β),typeof(α)}(r, T(Z), T(δβ₁), α, β, α)
267269
end
268270

271+
# Arbitrary case
269272
function StaggeredFiniteDifferences(r::V, Z=one(T),
270273
δβ₁=schafer_corner_fix(local_step(r,1), Z)) where {T,V<:AbstractVector{T}}
271274
issorted(r) ||
@@ -274,6 +277,8 @@ struct StaggeredFiniteDifferences{T,V<:AbstractVector{T},A,B} <: AbstractFiniteD
274277
N = length(r)
275278
α = zeros(T, N-1)
276279
β = zeros(T, N)
280+
γ = zeros(T, N)
281+
δ = zeros(T, N-1)
277282

278283
= vcat(r, 2r[end]-r[end-1])
279284
a = 2r[1]-r[2]
@@ -283,19 +288,21 @@ struct StaggeredFiniteDifferences{T,V<:AbstractVector{T},A,B} <: AbstractFiniteD
283288
if j < N
284289
d = r̃[j+2]
285290
# Eq. (A13) Krause 1999
286-
α[j] = 2/((c-b)*√((d-b)*(c-a)))*((b+c)/2)^2/(b*c)
291+
δ[j] = 2/(((d-b)*(c-a)))*((b+c)/2)^2/(b*c)
292+
α[j] = δ[j]/(c-b)
287293
end
288294

289295
# Eq. (A14) Krause 1999
290-
β[j] = 1/(c-a)*(1/(c-b)*((c+b)/2b)^2 +
291-
1/(b-a)*((b+a)/2b)^2)
296+
fp = ((c+b)/2b)^2
297+
fm = ((b+a)/2b)^2
298+
β[j] = 1/(c-a)*(1/(c-b)*fp + 1/(b-a)*fm)
292299

293300
a,b,c = b,c,d
294301
end
295302

296303
β[1] += δβ₁
297304

298-
new{T,V,typeof(α),typeof(β)}(r, T(Z), T(δβ₁), α, β)
305+
new{T,V,typeof(α),typeof(β),typeof(δ)}(r, T(Z), T(δβ₁), α, β, δ)
299306
end
300307

301308
# Constructor of uniform grid

test/fd/derivatives.jl

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -128,12 +128,14 @@ end
128128
@test isapprox(ph, order, atol=0.03) || ph > order
129129
end
130130
@testset "kind = StaggeredFiniteDifferences" begin
131-
let (order,B) = (2,StaggeredFiniteDifferences)
132-
@info "$B derivative accuracy"
133-
dd = b-a
131+
dd = b-a
132+
@testset "$(label)" for (order,label,fun) = [(2.0, "Uniform", N -> (N,dd/(N+1))),
133+
(2.5, "Non-uniform", N -> (dd*(1 .- cos.(π*range(0,stop=1,length=N+2)[2:end-1]))/2,))]
134+
@info "$(label) StaggeredFiniteDifferences derivative accuracy"
134135
hs,ϵg,ϵh,ϵh′,pg,ph,ph′ = compute_derivative_errors(Ns, x -> f(x-dd/2), x -> g(x-dd/2), x -> h(x-dd/2), 1) do N
135-
Δx = dd/(N+1)
136-
StaggeredFiniteDifferences(N, Δx, 1.0, 0.0),Δx
136+
R = StaggeredFiniteDifferences(fun(N)..., 1.0, 0.0)
137+
Δx = maximum(diff(R.r))
138+
R, Δx
137139
end
138140

139141
@test isapprox(pg, order, atol=0.03) || pg > order

0 commit comments

Comments
 (0)