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

Commit 96ffd70

Browse files
Merge pull request #227 from fgerick/irregular_grid_fix
Irregular grid fix
2 parents a5bb1df + 0d45208 commit 96ffd70

4 files changed

Lines changed: 89 additions & 50 deletions

File tree

src/derivative_operators/concretization.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ function Base.copyto!(L::AbstractMatrix{T}, A::DerivativeOperator{T}, N::Int) wh
2828

2929
for i in bl+1:N-bl
3030
cur_coeff = get_coeff(i)
31-
stencil = eltype(A.stencil_coefs) <: AbstractVector ? A.stencil_coefs[i] : A.stencil_coefs
31+
stencil = eltype(A.stencil_coefs) <: AbstractVector ? A.stencil_coefs[i-bl] : A.stencil_coefs
3232
cur_stencil = use_winding(A) && cur_coeff < 0 ? reverse(stencil) : stencil
3333
L[i,i+1-stencil_pivot:i-stencil_pivot+stencil_length] = cur_coeff * cur_stencil
3434
end

src/derivative_operators/derivative_operator.jl

Lines changed: 20 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,18 @@ function CenteredDifference{N}(derivative_order::Int,
6767
)
6868
end
6969

70+
function generate_coordinates(i::Int, stencil_x, dummy_x, dx::AbstractVector{T}) where T <: Real
71+
len = length(stencil_x)
72+
stencil_x .= stencil_x.*zero(T)
73+
for idx in 1:div(len,2)
74+
shifted_idx1 = index(idx, len)
75+
shifted_idx2 = index(-idx, len)
76+
stencil_x[shifted_idx1] = stencil_x[shifted_idx1-1] + dx[i+idx-1]
77+
stencil_x[shifted_idx2] = stencil_x[shifted_idx2+1] - dx[i-idx]
78+
end
79+
return stencil_x
80+
end
81+
7082
function CenteredDifference{N}(derivative_order::Int,
7183
approximation_order::Int, dx::AbstractVector{T},
7284
len::Int, coeff_func=nothing) where {T<:Real,N}
@@ -78,28 +90,18 @@ function CenteredDifference{N}(derivative_order::Int,
7890

7991
interior_x = boundary_point_count+2:len+1-boundary_point_count
8092
dummy_x = -div(stencil_length,2) : div(stencil_length,2)-1
81-
boundary_x = -boundary_stencil_length+1:0
82-
93+
low_boundary_x = [zero(T); cumsum(dx[1:boundary_stencil_length-1])]
94+
high_boundary_x = cumsum(dx[end-boundary_stencil_length+1:end])
8395
# Because it's a N x (N+2) operator, the last stencil on the sides are the [b,0,x,x,x,x] stencils, not the [0,x,x,x,x,x] stencils, since we're never solving for the derivative at the boundary point.
8496
deriv_spots = (-div(stencil_length,2)+1) : -1
85-
boundary_deriv_spots = boundary_x[2:div(stencil_length,2)]
86-
87-
function generate_coordinates(i, stencil_x, dummy_x, dx)
88-
len = length(stencil_x)
89-
stencil_x .= stencil_x.*zero(T)
90-
for idx in 1:div(len,2)
91-
shifted_idx1 = index(idx, len)
92-
shifted_idx2 = index(-idx, len)
93-
stencil_x[shifted_idx1] = stencil_x[shifted_idx1-1] + dx[i+idx-1]
94-
stencil_x[shifted_idx2] = stencil_x[shifted_idx2+1] - dx[i-idx]
95-
end
96-
return stencil_x
97-
end
9897

99-
stencil_coefs = convert(SVector{length(interior_x)}, [convert(SVector{stencil_length, T}, calculate_weights(derivative_order, zero(T), generate_coordinates(i, stencil_x, dummy_x, dx))) for i in interior_x])
100-
_low_boundary_coefs = SVector{boundary_stencil_length, T}[convert(SVector{boundary_stencil_length, T}, calculate_weights(derivative_order, oneunit(T)*x0, boundary_x)) for x0 in boundary_deriv_spots]
98+
stencil_coefs = [convert(SVector{stencil_length, T}, calculate_weights(derivative_order, zero(T), generate_coordinates(i, stencil_x, dummy_x, dx))) for i in interior_x]
99+
_low_boundary_coefs = SVector{boundary_stencil_length, T}[convert(SVector{boundary_stencil_length, T},
100+
calculate_weights(derivative_order, low_boundary_x[i+1], low_boundary_x)) for i in 1:boundary_point_count]
101101
low_boundary_coefs = convert(SVector{boundary_point_count},_low_boundary_coefs)
102-
high_boundary_coefs = convert(SVector{boundary_point_count},reverse(SVector{boundary_stencil_length, T}[reverse(low_boundary_coefs[i]) for i in 1:boundary_point_count]))
102+
_high_boundary_coefs = SVector{boundary_stencil_length, T}[convert(SVector{boundary_stencil_length, T},
103+
calculate_weights(derivative_order, high_boundary_x[end-i], high_boundary_x)) for i in boundary_point_count:-1:1]
104+
high_boundary_coefs = convert(SVector{boundary_point_count},_high_boundary_coefs)
103105

104106
coefficients = coeff_func isa Nothing ? nothing : Vector{T}(undef,len)
105107

test/derivative_operators_interface.jl

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -146,55 +146,56 @@ end
146146

147147
@testset "Correctness of Non-Uniform Stencils" begin
148148
x = [0., 0.08, 0.1, 0.15, 0.19, 0.26, 0.29]
149+
nx = length(x)
149150
dx = diff(x)
150151

151152
# Second-Order First Derivative
152-
L = CenteredDifference(1, 2, dx, 5)
153+
L = CenteredDifference(1, 2, dx, nx-2)
153154
correct = analyticCtrOneTwoIrr()
154155

155156
# Check that stencils agree with correct
156157
for (i,coefs) in enumerate(L.stencil_coefs)
157158
@test Array(coefs) correct[i,correct[i,:] .!= 0.]
158159
end
159-
@test_broken Array(L) correct # All of these concretizations
160-
@test_broken sparse(L) correct # only give the first three
161-
@test_broken BandedMatrix(L) correct # rows of the computed stencil coefficients
160+
@test Array(L) correct
161+
@test sparse(L) correct
162+
@test BandedMatrix(L) correct
162163

163164
# Second-Order Second Derivative
164-
L = CenteredDifference(2, 2, dx, 5)
165+
L = CenteredDifference(2, 2, dx, nx-2)
165166
correct = analyticCtrTwoTwoIrr()
166167

167168
# Check that stencils agree with correct
168169
for (i,coefs) in enumerate(L.stencil_coefs)
169170
@test Array(coefs) correct[i,correct[i,:] .!= 0.]
170171
end
171-
@test_broken Array(L) correct # same issue as previous derivative
172-
@test_broken sparse(L) correct
173-
@test_broken BandedMatrix(L) correct
172+
@test Array(L) correct
173+
@test sparse(L) correct
174+
@test BandedMatrix(L) correct
174175

175176
# Fourth-Order Second Derivative
176-
L = CenteredDifference(2, 4, dx, 5)
177+
L = CenteredDifference(2, 4, dx, nx-2)
177178
correct = analyticCtrTwoFourIrr()
178179

179180
# Check that stencils agree with correct
180181
for (i,coefs) in enumerate(L.stencil_coefs)
181182
@test Array(coefs) correct[i,correct[i,:] .!= 0.]
182183
end
183-
@test_broken Array(L) correct # L.stencil_coefs is populated, but the concretization doesn't work. It appears to be an issue of improper calculation of indexing from the various lengths computed during construction (e.g. boundary_stencil_length, len) and potentially the fact that "len" doesn't seem to specify the number of grid points at which we compute finite differences but appears to specify the location of the last grid point at which we compute finite differences (so if X is a 5-length vector, entering len = 2 means computing FDs for X[2] and X[3])
184-
@test_broken sparse(L) correct
185-
@test_broken BandedMatrix(L) correct
184+
@test Array(L)[2:end-1,:] correct
185+
@test sparse(L)[2:end-1,:] correct
186+
@test BandedMatrix(L)[2:end-1,:] correct
186187

187188
# Second-Order Fourth Derivative
188-
L = CenteredDifference(4, 2, dx, 5)
189+
L = CenteredDifference(4, 2, dx, nx-2)
189190
correct = analyticCtrFourTwoIrr()
190191

191192
# Check that stencils agree with correct
192193
for (i,coefs) in enumerate(L.stencil_coefs)
193194
@test Array(coefs) correct[i,correct[i,:] .!= 0.]
194195
end
195-
@test_broken Array(L) correct
196-
@test_broken sparse(L) correct
197-
@test_broken BandedMatrix(L) correct
196+
@test Array(L)[2:end-1,:] correct
197+
@test sparse(L)[2:end-1,:] correct
198+
@test BandedMatrix(L)[2:end-1,:] correct
198199
end
199200

200201
# tests for full and sparse function
Lines changed: 51 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,66 @@
1-
using DiffEqOperators
2-
3-
n = 100
4-
x=0.0:0.005:2π
5-
xprime = x[2:(end-1)]
6-
dx=diff(x)
7-
y = exp.(π*x)
8-
y_im = exp.(π*im*x)
9-
yim_ = y_im[2:(end-1)]
1+
using DiffEqOperators, SparseArrays, LinearAlgebra
2+
3+
x = 0.0:0.01:π
4+
x_ = x[2:end-1]
5+
dx = diff(x)
6+
y = sin.(2x)
107
y_ = y[2:(end-1)]
8+
dy = [2cos.(2x_),-4sin.(2x_),-8cos.(2x_),16y_,32cos.(2x_)]
9+
10+
11+
12+
# test concretization against regular grid operator
13+
for dor in 1:4, aor in 2:2:6
14+
Dr = CenteredDifference(dor,aor,dx[1],length(x)-2)
15+
Dir = CenteredDifference(dor,aor,dx,length(x)-2)
16+
17+
@test sparse(Dr)sparse(Dir)
18+
@test Array(Dr)Array(Dir)
1119

12-
@test_broken for dor in 1:6, aor in 1:6
20+
end
21+
22+
# test irregular grid operator with regular grid
23+
for dor in 1:4, aor in 2:6
1324

14-
D1 = CenteredDifference(dor,aor,dx,length(x))
25+
D1 = CenteredDifference(dor,aor,dx,length(x)-2)
1526

1627
#take derivative
1728
yprime1 = D1*y
1829

1930
#test result
20-
@test_broken yprime1 ^dor)*y_ # test operator with known derivative of exp(kx)
31+
@test yprime1 dy[dor] atol = 10.0^(1-aor)#2test operator with known derivative of exp(kx)
32+
33+
#TODO: implement specific tests for the left and right boundary regions, waiting until after update
34+
end
2135

22-
#take derivatives
23-
y_imprime1 = D1*y_im
36+
37+
# test irregular grid
38+
39+
x = sin.(0.0:0.05:π)
40+
x = cumsum(x)
41+
x = x/x[end]*π
42+
x_ = x[2:end-1]
43+
dx = diff(x)
44+
y = sin.(2x)
45+
y_ = y[2:(end-1)]
46+
dy = [2cos.(2x_), -4sin.(2x_), -8cos.(2x_), 16y_, 32cos.(2x_)]
47+
48+
for dor in 1:4, aor in 4:10
49+
50+
D1 = CenteredDifference(dor,aor,dx,length(x)-2)
51+
52+
#take derivative
53+
yprime1 = D1*y
2454

2555
#test result
26-
@test_broken y_imprime1 ((pi*im)^dor)*yim_ # test operator with known derivative of exp(jkx)
56+
tol = 2*10.0^(2-aor)*maximum(dx)^(2-dor)
57+
# error estimate is fairly difficult for high order derivatives and small dx.
58+
59+
# err = norm(yprime1.-dy[dor])
60+
# @show err
61+
# @show tol
2762

63+
@test yprime1 dy[dor] atol = tol #2test operator with known derivative of exp(kx)
2864

2965
#TODO: implement specific tests for the left and right boundary regions, waiting until after update
3066
end

0 commit comments

Comments
 (0)