Skip to content

Commit 0b0e7e8

Browse files
authored
Merge pull request #616 from maltezfaria/cubic-free-bc
Fix free boundary condition on `Cubic`
2 parents 08949a3 + 82a75fd commit 0b0e7e8

File tree

2 files changed

+44
-10
lines changed

2 files changed

+44
-10
lines changed

src/b-splines/cubic.jl

+27-10
Original file line numberDiff line numberDiff line change
@@ -232,16 +232,33 @@ end
232232
continuous derivative at the second-to-last cell boundary; this means
233233
`y_1'''(2) = y_2'''(2)`, yielding
234234
235-
1 cm -3 c + 3 cp -1 cpp = 0
236-
"""
237-
function prefiltering_system(::Type{T}, ::Type{TC}, n::Int,
238-
degree::Cubic{<:Free}) where {T,TC}
239-
dl, d, du = inner_system_diags(T,n,degree)
240235
241-
specs = WoodburyMatrices.sparse_factors(T, n,
242-
(1, n, du[1]),
243-
(n, 1, dl[end])
244-
)
236+
-1 cm + 4 c - 6 cp + 4 cpp - 1 cppp = 0
245237
246-
Woodbury(lut!(dl, d, du), specs...), zeros(TC, n)
238+
This enforces continuity of the third derivative, which is appropriate for cubic splines
239+
(in contrast to the quadratic case which enforces continuity of the second derivative).
240+
241+
"""
242+
function prefiltering_system(
243+
::Type{T},
244+
::Type{TC},
245+
n::Int,
246+
degree::Cubic{<:Free},
247+
) where {T,TC}
248+
dl, d, du = inner_system_diags(T, n, degree)
249+
d[1] = d[end] = -1
250+
du[1] = dl[end] = 4
251+
252+
specs = WoodburyMatrices.sparse_factors(
253+
T,
254+
n,
255+
(1, 3, -6),
256+
(1, 4, 4),
257+
(1, 5, -1),
258+
(n, n - 2, -6),
259+
(n, n - 3, 4),
260+
(n, n - 4, -1),
261+
)
262+
263+
return Woodbury(lut!(dl, d, du), specs...), zeros(TC, n)
247264
end

test/b-splines/cubic.jl

+17
Original file line numberDiff line numberDiff line change
@@ -90,4 +90,21 @@
9090
itp = interpolate(rand(5, 9), BSpline(Cubic(Flat(OnGrid()))))
9191
@test itp == Interpolations.BSplineInterpolation(itp.coefs, itp.it, itp.parentaxes)
9292
@test_throws ArgumentError Interpolations.BSplineInterpolation(itp.coefs, itp.it, (2:3, 2:10))
93+
94+
# Issue 594
95+
@testset "Free BC" begin
96+
# should be exact for polynomials of degree <= 3 (up to rounding error)
97+
ix = 1:15
98+
f = x -> x^3 - 2x^2 + 3x - 4
99+
A = map(f, ix)
100+
itp = interpolate(A, BSpline(Cubic(Free(OnGrid()))))
101+
@test all(x -> itp(x) f(x), 1:0.1:15)
102+
103+
# also in 2d
104+
f2(x, y) = x^3 - 2x^2 + 3x - 4 + 2y^3 - 2y^2 + 3y - 4
105+
iy = 1:15
106+
A = map(I -> f2(I[1], I[2]), Iterators.product(ix, iy))
107+
itp = interpolate(A, BSpline(Cubic(Free(OnGrid()))))
108+
@test all(x -> itp(x...) f2(x...), Iterators.product(1:0.1:15, 1:0.1:15))
109+
end
93110
end

0 commit comments

Comments
 (0)