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

Commit c034ccf

Browse files
Merge pull request #149 from xtalax/SplitBC-dev
#148 Changes implemented
2 parents cd3dcda + 6327143 commit c034ccf

File tree

8 files changed

+69
-45
lines changed

8 files changed

+69
-45
lines changed

src/DiffEqOperators.jl

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@ abstract type AbstractMatrixFreeOperator{T} <: AbstractDiffEqLinearOperator{T} e
1414
include("matrixfree_operators.jl")
1515
include("jacvec_operators.jl")
1616

17+
### Utilities
18+
include("utils.jl")
19+
1720
### Boundary Padded Arrays
1821
include("boundary_padded_arrays.jl")
1922

src/boundary_padded_arrays.jl

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# Boundary Padded Arrays
22
abstract type AbstractBoundaryPaddedArray{T, N} <: AbstractArray{T, N} end
3-
3+
abstract type AbstractDirectionalBoundaryPaddedArray{T, N, D} <: AbstractBoundaryPaddedArray{T, N} end
4+
abstract type AbstractComposedBoundaryPaddedArray{T, N} <: AbstractBoundaryPaddedArray{T,N} end
45
"""
56
A vector type that extends a vector u with ghost points at either end
67
"""
@@ -9,6 +10,7 @@ struct BoundaryPaddedVector{T,T2 <: AbstractVector{T}} <: AbstractBoundaryPadded
910
r::T
1011
u::T2
1112
end
13+
1214
Base.length(Q::BoundaryPaddedVector) = length(Q.u) + 2
1315
Base.size(Q::BoundaryPaddedVector) = (length(Q.u) + 2,)
1416
Base.lastindex(Q::BoundaryPaddedVector) = Base.length(Q)
@@ -27,7 +29,7 @@ end
2729
Higher dimensional generalization of BoundaryPaddedVector, pads an array of dimension N along the dimension D with 2 Arrays of dimension N-1, stored in lower and upper
2830
2931
"""
30-
struct BoundaryPaddedArray{T, D, N, M, V<:AbstractArray{T, N}, B<: AbstractArray{T, M}} <: AbstractBoundaryPaddedArray{T,N}
32+
struct BoundaryPaddedArray{T, D, N, M, V<:AbstractArray{T, N}, B<: AbstractArray{T, M}} <: AbstractDirectionalBoundaryPaddedArray{T,N, D}
3133
lower::B #an array of dimension M = N-1, used to extend the lower index boundary
3234
upper::B #Ditto for the upper index boundary
3335
u::V
@@ -59,9 +61,9 @@ function compose(padded_arrays::BoundaryPaddedArray...)
5961
Ds = getaxis.(padded_arrays)
6062
(length(padded_arrays) == N) || throw(ArgumentError("The padded_arrays must cover every dimension - make sure that the number of padded_arrays is equal to ndims(u)."))
6163
for D in Ds
62-
length(setdiff(Ds, D)) == (N-1) || throw(ArgumentError("There are multiple Arrays that extend along dimension $D - make sure every dimension has a unique extension"))
64+
length(setdiff(Ds, D)) < N || throw(ArgumentError("There are multiple Arrays that extend along dimension $D - make sure every dimension has a unique extension"))
6365
end
64-
reduce((|), fill(padded_arrays[1].u, (length(padded_arrays),)) .== getfield.(padded_arrays, :u)) || throw(ArgumentError("The padded_arrays do not all extend the same u!"))
66+
any(fill(padded_arrays[1].u, (length(padded_arrays),)) .== getfield.(padded_arrays, :u)) || throw(ArgumentError("The padded_arrays do not all extend the same u!"))
6567
padded_arrays = padded_arrays[sortperm([Ds...])]
6668
lower = [padded_array.lower for padded_array in padded_arrays]
6769
upper = [padded_array.upper for padded_array in padded_arrays]
@@ -71,7 +73,7 @@ end
7173

7274
# Composed BoundaryPaddedArray
7375

74-
struct ComposedBoundaryPaddedArray{T, N, M, V<:AbstractArray{T, N}, B<: AbstractArray{T, M}} <: AbstractBoundaryPaddedArray{T, N}
76+
struct ComposedBoundaryPaddedArray{T, N, M, V<:AbstractArray{T, N}, B<: AbstractArray{T, M}} <: AbstractComposedBoundaryPaddedArray{T, N}
7577
lower::Vector{B}
7678
upper::Vector{B}
7779
u::V
@@ -96,8 +98,7 @@ Ax, Ay,... = decompose(A::ComposedBoundaryPaddedArray)
9698
9799
Decomposes a ComposedBoundaryPaddedArray in to components that extend along each dimension individually
98100
"""
99-
decompose(A::ComposedBoundaryPaddedArray) = Tuple([BoundaryPaddedArray{gettype(A), ndims(A), ndims(A)-1, typeof(lower[1])}(A.lower[i], A.upper[i], A.u) for i in 1:ndims(A)])
100-
101+
decompose(A::ComposedBoundaryPaddedArray) = Tuple([BoundaryPaddedArray{gettype(A), i, ndims(A), ndims(A)-1, typeof(lower[1])}(A.lower[i], A.upper[i], A.u) for i in 1:ndims(A)])
101102

102103
Base.length(Q::AbstractBoundaryPaddedArray) = reduce((*), size(Q))
103104
Base.firstindex(Q::AbstractBoundaryPaddedArray, d::Int) = 1
@@ -106,9 +107,6 @@ Base.lastindex(Q::AbstractBoundaryPaddedArray, d::Int) = size(Q)[d]
106107
gettype(Q::AbstractBoundaryPaddedArray{T,N}) where {T,N} = T
107108
Base.ndims(Q::AbstractBoundaryPaddedArray{T,N}) where {T,N} = N
108109

109-
add_dim(A::AbstractArray, i) = reshape(A, size(A)...,i)
110-
add_dim(i) = i
111-
112110
function Base.getindex(Q::BoundaryPaddedArray{T,D,N,M,V,B}, _inds::Vararg{Int,N}) where {T,D,N,M,V,B} #supports range and colon indexing!
113111
inds = [_inds...]
114112
S = size(Q)
@@ -139,14 +137,14 @@ function Base.getindex(Q::ComposedBoundaryPaddedArray{T, N, M, V, B} , inds::Var
139137
for (dim, index) in enumerate(inds)
140138
if index == 1
141139
_inds = inds[setdiff(1:N, dim)]
142-
if (1 _inds) | reduce((|), S[setdiff(1:N, dim)] .== _inds)
140+
if (1 _inds) | any(S[setdiff(1:N, dim)] .== _inds)
143141
return zero(T)
144142
else
145143
return Q.lower[dim][(_inds.-1)...]
146144
end
147145
elseif index == S[dim]
148146
_inds = inds[setdiff(1:N, dim)]
149-
if (1 _inds) | reduce((|), S[setdiff(1:N, dim)] .== _inds)
147+
if (1 _inds) | any(S[setdiff(1:N, dim)] .== _inds)
150148
return zero(T)
151149
else
152150
return Q.upper[dim][(_inds.-1)...]

src/derivative_operators/BC_operators.jl

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -37,12 +37,12 @@ end
3737
The non identity part of Qa is qa:= -b`₁/b0 = -β.*s[2:end]/(α+β*s[1]/Δx). The constant part is Qb = γ/(α+β*s[1]/Δx)
3838
do the same at the other boundary (amounts to a flip of s[2:end], with the other set of boundary coeffs)
3939
"""
40-
struct RobinBC{T} <: AffineBC{T}
41-
a_l::Vector{T}
40+
struct RobinBC{T, V<:AbstractVector{T}} <: AffineBC{T}
41+
a_l::V
4242
b_l::T
43-
a_r::Vector{T}
43+
a_r::V
4444
b_r::T
45-
function RobinBC(l::AbstractVector{T}, r::AbstractVector{T}, dx::T, order = 1) where {T}
45+
function RobinBC(l::NTuple{3,T}, r::NTuple{3,T}, dx::T, order = 1) where {T}
4646
αl, βl, γl = l
4747
αr, βr, γr = r
4848

@@ -54,7 +54,7 @@ struct RobinBC{T} <: AffineBC{T}
5454
b_l = γl/(αl+βl*s[1]/dx)
5555
b_r = γr/(αr-βr*s[1]/dx)
5656

57-
return new{T}(a_l, b_l, a_r, b_r)
57+
return new{T, typeof(a_l)}(a_l, b_l, a_r, b_r)
5858
end
5959
function RobinBC(l::AbstractVector{T}, r::AbstractVector{T}, dx::AbstractVector{T}, order = 1) where {T}
6060
αl, βl, γl = l
@@ -73,7 +73,7 @@ struct RobinBC{T} <: AffineBC{T}
7373
b_l = γl/denom_l
7474
b_r = γr/denom_r
7575

76-
return new{T}(a_l, b_l, a_r, b_r)
76+
return new{T, typeof(a_l)}(a_l, b_l, a_r, b_r)
7777
end
7878
end
7979

@@ -91,10 +91,10 @@ This time there are multiple stencils for multiple derivative orders - these can
9191
All components that multiply u(0) are factored out, turns out to only involve the first colum of S, s̄0. The rest of S is denoted S`. the coeff of u(0) is s̄0⋅ᾱ[3:end] + α[2].
9292
the remaining components turn out to be ᾱ[3:end]⋅(S`ū`) or equivalantly (transpose(ᾱ[3:end])*S`)⋅ū`. Rearranging, a stencil q_a to be dotted with ū` upon extension can readily be found, along with a constant component q_b
9393
"""
94-
struct GeneralBC{T} <:AffineBC{T}
95-
a_l::Vector{T}
94+
struct GeneralBC{T, L<:AbstractVector{T}, R<:AbstractVector{T}} <:AffineBC{T}
95+
a_l::L
9696
b_l::T
97-
a_r::Vector{T}
97+
a_r::R
9898
b_r::T
9999
function GeneralBC(αl::AbstractVector{T}, αr::AbstractVector{T}, dx::T, order = 1) where {T}
100100
nl = length(αl)
@@ -116,11 +116,11 @@ struct GeneralBC{T} <:AffineBC{T}
116116
denomr = αr[2] .+ αr[3:end] s0_r
117117

118118
a_l = -transpose(transpose(αl[3:end]) * Sl) ./denoml
119-
a_r = -transpose(transpose(αr[3:end]) * Sr) ./denomr
119+
a_r = reverse(-transpose(transpose(αr[3:end]) * Sr) ./denomr)
120120

121121
b_l = -αl[1]/denoml
122122
b_r = -αr[1]/denomr
123-
new{T}(a_l,b_l,reverse!(a_r),b_r)
123+
new{T, typeof(a_l), typeof(a_r)}(a_l,b_l,a_r,b_r)
124124
end
125125

126126
function GeneralBC(αl::AbstractVector{T}, αr::AbstractVector{T}, dx::AbstractVector{T}, order = 1) where {T}
@@ -145,22 +145,22 @@ struct GeneralBC{T} <:AffineBC{T}
145145
denomr = αr[2] .+ αr[3:end] s0_r
146146

147147
a_l = -transpose(transpose(αl[3:end]) * Sl) ./denoml
148-
a_r = -transpose(transpose(αr[3:end]) * Sr) ./denomr
148+
a_r = reverse(-transpose(transpose(αr[3:end]) * Sr) ./denomr)
149149

150150
b_l = -αl[1]/denoml
151151
b_r = -αr[1]/denomr
152-
new{T}(a_l,b_l,reverse!(a_r),b_r)
152+
new{T, typeof(a_l), typeof(a_r)}(a_l,b_l,a_r,b_r)
153153
end
154154
end
155155

156156

157157

158158
#implement Neumann and Dirichlet as special cases of RobinBC
159-
NeumannBC::AbstractVector{T}, dx::Union{AbstractVector{T}, T}, order = 1) where T = RobinBC([zero(T), one(T), α[1]], [zero(T), one(T), α[2]], dx, order)
160-
DirichletBC(αl::T, αr::T) where T = RobinBC([one(T), zero(T), αl], [one(T), zero(T), αr], 1.0, 2.0 )
159+
NeumannBC::NTuple{2,T}, dx::Union{AbstractVector{T}, T}, order = 1) where T = RobinBC((zero(T), one(T), α[1]), (zero(T), one(T), α[2]), dx, order)
160+
DirichletBC(αl::T, αr::T) where T = RobinBC((one(T), zero(T), αl), (one(T), zero(T), αr), 1.0, 2.0 )
161161
#specialized constructors for Neumann0 and Dirichlet0
162162
Dirichlet0BC(T::Type) = DirichletBC(zero(T), zero(T))
163-
Neumann0BC(dx::Union{AbstractVector{T}, T}, order = 1) where T = NeumannBC([zero(T), zero(T)], dx, order)
163+
Neumann0BC(dx::Union{AbstractVector{T}, T}, order = 1) where T = NeumannBC((zero(T), zero(T)), dx, order)
164164

165165
# other acceptable argument signatures
166166
#RobinBC(al::T, bl::T, cl::T, dx_l::T, ar::T, br::T, cr::T, dx_r::T, order = 1) where T = RobinBC([al,bl, cl], [ar, br, cr], dx_l, order)

src/derivative_operators/multi_dim_bc_operators.jl

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@ abstract type MultiDimensionalBC{T, N} <: AbstractBC{T} end
1111
u_temp
1212
end
1313

14+
"""
15+
slice_rmul lets you multiply each vector like strip of an array `u` with a linear operator `A`, sliced along dimension `dim`
16+
"""
1417
function slice_rmul(A::AbstractDiffEqLinearOperator, u::AbstractArray{T,N}, dim::Int) where {T,N}
1518
@assert N != 1
1619
u_temp = similar(u)
@@ -42,9 +45,6 @@ function slice_rmul(A::AbstractArray{B,M}, u::AbstractArray{T,N}, dim::Int) wher
4245
return (lower, upper)
4346
end
4447

45-
"""
46-
slicemul is the only limitation on the BCs here being used up to arbitrary dimension, an N dimensional implementation is needed.
47-
"""
4848

4949
struct MultiDimDirectionalBC{T<:Number, B<:AtomicBC{T}, D, N, M} <: MultiDimensionalBC{T, N}
5050
BCs::Array{B,M} #dimension M=N-1 array of BCs to extend dimension D
@@ -94,17 +94,16 @@ MultiDimBC(BC::B, s) where {B<:AtomicBC} = Tuple([MultiDimDirectionalBC{gettype(
9494

9595
PeriodicBC{T}(s) where T = MultiDimBC(PeriodicBC{T}(), s)
9696

97-
NeumannBC::AbstractVector{T}, dxyz, order, s) where T = RobinBC([zero(T), one(T), α[1]], [zero(T), one(T), α[2]], dxyz, order, s)
98-
DirichletBC(αl::T, αr::T, s) where T = RobinBC([one(T), zero(T), αl], [one(T), zero(T), αr], [ones(T, si) for si in s], 2.0, s)
97+
NeumannBC::NTuple{2,T}, dxyz, order, s) where T = RobinBC((zero(T), one(T), α[1]), (zero(T), one(T), α[2]), dxyz, order, s)
98+
DirichletBC(αl::T, αr::T, s) where T = RobinBC((one(T), zero(T), αl), (one(T), zero(T), αr), [ones(T, si) for si in s], 2.0, s)
9999

100100
Dirichlet0BC(T::Type, s) = DirichletBC(zero(T), zero(T), s)
101-
Neumann0BC(T::Type, dxyz, order, s) = NeumannBC([zero(T), zero(T)], dxyz, order, s)
101+
Neumann0BC(T::Type, dxyz, order, s) = NeumannBC((zero(T), zero(T)), dxyz, order, s)
102102

103-
RobinBC(l::AbstractVector{T}, r::AbstractVector{T}, dxyz, order, s) where {T} = Tuple([MultiDimDirectionalBC{T, RobinBC{T}, dim, length(s), length(s)-1}(fill(RobinBC(l, r, dxyz[dim], order), s[setdiff(1:length(s), dim)])) for dim in 1:length(s)])
104-
GeneralBC(αl::AbstractVector{T}, αr::AbstractVector{T}, dxyz, order, s) where {T} = Tuple([MultiDimDirectionalBC{T, GeneralBC{T}, dim, length(s), length(s)-1}(fill(GeneralBC(αl, αr, dxyz[dim], order), s[setdiff(1:length(s), dim)])) for dim in 1:length(s)])
103+
RobinBC(l::NTuple{3,T}, r::NTuple{3,T}, dxyz, order, s) where {T} = Tuple([MultiDimDirectionalBC{T, RobinBC{T}, dim, length(s), length(s)-1}(fill(RobinBC(l, r, dxyz[dim], order), perpindex(s,dim))) for dim in 1:length(s)])
104+
GeneralBC(αl::AbstractVector{T}, αr::AbstractVector{T}, dxyz, order, s) where {T} = Tuple([MultiDimDirectionalBC{T, GeneralBC{T}, dim, length(s), length(s)-1}(fill(GeneralBC(αl, αr, dxyz[dim], order),perpindex(s,dim))) for dim in 1:length(s)])
105105

106106

107-
perpsize(A::AbstractArray{T,N}, dim::Integer) where {T,N} = size(A)[setdiff(1:N, dim)] #the size of A perpendicular to dim
108107

109108
"""
110109
Q = compose(BCs...)

src/utils.jl

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
2+
"""
3+
A function that creates a tuple of CartesianIndices of unit length and `N` dimensions, one pointing along each dimension
4+
"""
5+
function unit_indices(N::Int) #create unit CartesianIndex for each dimension
6+
out = Vector{CartesianIndex{N}}(undef, N)
7+
null = zeros(Int64, N)
8+
for i in 1:N
9+
unit_i = copy(null)
10+
unit_i[i] = 1
11+
out[i] = CartesianIndex(Tuple(unit_i))
12+
end
13+
Tuple(out)
14+
end
15+
16+
add_dims(A::AbstractArray, n::Int) = cat(ndims(a) + n, a)
17+
18+
""
19+
perpindex(A, dim::Integer) = A[setdiff(1:length(A), dim)]
20+
21+
"""
22+
the size of A perpendicular to dim
23+
"""
24+
perpsize(A::AbstractArray{T,N}, dim::Integer) where {T,N} = size(A)[setdiff(1:N, dim)]

test/MultiDimBC_test.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ m = 15
99
A = rand(n,m)
1010

1111
#Create atomic BC
12-
q1 = RobinBC([1.0, 2.0, 3.0], [0.0, -1.0, 2.0], 0.1, 4.0)
12+
q1 = RobinBC((1.0, 2.0, 3.0), (0.0, -1.0, 2.0), 0.1, 4.0)
1313
q2 = PeriodicBC{Float64}()
1414

1515
BCx = vcat(fill(q1, div(m,2)), fill(q2, m-div(m,2))) #The size of BCx has to be all size components *except* for x
@@ -44,7 +44,7 @@ o = 12
4444
A = rand(n,m, o)
4545

4646
#Create atomic BC
47-
q1 = RobinBC([1.0, 2.0, 3.0], [0.0, -1.0, 2.0], 0.1, 4.0)
47+
q1 = RobinBC((1.0, 2.0, 3.0), (0.0, -1.0, 2.0), 0.1, 4.0)
4848
q2 = PeriodicBC{Float64}()
4949

5050
BCx = vcat(fill(q1, (div(m,2), o)), fill(q2, (m-div(m,2), o))) #The size of BCx has to be all size components *except* for x

test/bc_coeff_compositions.jl

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ end
4242
cr = rand()
4343
dx = rand()
4444

45-
Q = RobinBC([al, bl, cl], [ar, br, cr], dx)
45+
Q = RobinBC((al, bl, cl), (ar, br, cr), dx)
4646
N = 20
4747
L = CenteredDifference(4,4, 1.0, N)
4848
L2 = CenteredDifference(2,4, 1.0, N)
@@ -112,7 +112,7 @@ end
112112
N = length(x)
113113

114114
L = CenteredDifference(2, 2, dx, N)
115-
Q = RobinBC([1.0, 0.0, 0.0], [1.0, 0.0, 0.0], dx)
115+
Q = RobinBC((1.0, 0.0, 0.0), (1.0, 0.0, 0.0), dx)
116116
A = L*Q
117117

118118
analytic_L = second_derivative_stencil(N) ./ dx^2
@@ -155,7 +155,7 @@ end
155155
N = length(x)
156156

157157
L = CenteredDifference(2, 2, dx, N)
158-
Q = RobinBC([1.0, 0.0, 4.0], [1.0, 0.0, 4.0], dx)
158+
Q = RobinBC((1.0, 0.0, 4.0), (1.0, 0.0, 4.0), dx)
159159
A = L*Q
160160

161161
analytic_L = second_derivative_stencil(N) ./ dx^2
@@ -203,7 +203,7 @@ end
203203
u = sin.(x)
204204

205205
L = CenteredDifference(4, 4, dx, N)
206-
Q = RobinBC([1.0, 0.0, sin(0.0)], [1.0, 0.0, sin(0.2+dx)], dx)
206+
Q = RobinBC((1.0, 0.0, sin(0.0)), (1.0, 0.0, sin(0.2+dx)), dx)
207207
A = L*Q
208208

209209
analytic_L = fourth_deriv_approx_stencil(N) ./ dx^4

test/robin.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ cr = rand(5)
1212

1313
# Construct 5 arbitrary RobinBC operators
1414
for i in 1:5
15-
Q = RobinBC([al[i], bl[i], cl[i]], [ar[i], br[i], cr[i]], dx[i])
15+
Q = RobinBC((al[i], bl[i], cl[i]), (ar[i], br[i], cr[i]), dx[i])
1616

1717
Q_L, Q_b = Array(Q,5i)
1818

@@ -46,7 +46,7 @@ end
4646
u0 = -4/10
4747
uend = 125/12
4848
u = Vector(1.0:10.0)
49-
Q = RobinBC([1.0, 6.0, 10.0], [1.0, 6.0, 10.0], 1.0, 3)
49+
Q = RobinBC((1.0, 6.0, 10.0), (1.0, 6.0, 10.0), 1.0, 3)
5050
urobinextended = Q*u
5151
@test urobinextended.l u0
5252
@test urobinextended.r uend

0 commit comments

Comments
 (0)