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

Commit bc05268

Browse files
committed
slicemul now fully N dimensional - BC operators work up to any N
1 parent c7ad2f7 commit bc05268

File tree

3 files changed

+39
-62
lines changed

3 files changed

+39
-62
lines changed

src/DiffEqOperators.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ export DiffEqScalar, DiffEqArrayOperator, DiffEqIdentity, JacVecOperator, getops
5252
export AbstractDerivativeOperator, DerivativeOperator,
5353
CenteredDifference, UpwindDifference
5454
export DirichletBC, Dirichlet0BC, NeumannBC, Neumann0BC, RobinBC, GeneralBC, MixedBC, MultiDimBC, PeriodicBC, BridgeBC,
55-
MultiDimDirectionalBC, ComposedMultiDimBC
55+
MultiDimDirectionalBC, ComposedMultiDimBC,
5656
compose, decompose, perpsize
5757

5858
export GhostDerivativeOperator

src/boundary_padded_arrays.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ Composes BoundaryPaddedArrays that extend the same u for each different dimensio
5454
5555
Ax Ay and Az can be passed in any order, as long as there is exactly one BoundaryPaddedArray that extends each dimension.
5656
"""
57-
function compose(padded_arrays::BoundaryPaddedArray...)
57+
function compose(padded_arrays::BoundaryPaddedArray ...)
5858
N = ndims(padded_arrays[1])
5959
Ds = getaxis.(padded_arrays)
6060
(length(padded_arrays) == N) || throw("The padded_arrays must cover every dimension - make sure that the number of padded_arrays is equal to ndims(u).")

src/derivative_operators/multi_dim_bc_operators.jl

Lines changed: 37 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -1,69 +1,46 @@
11

22
abstract type MultiDimensionalBC{T, N} <: AbstractBC{T} end
33

4-
"""
5-
slicemul is the only limitation on the BCs here being used up to arbitrary dimension, an N dimensional implementation is needed.
6-
"""
7-
@inline function slicemul(A::Array{B,1}, u::AbstractArray{T, 2}, dim::Integer) where {T, B<:AtomicBC{T}}
8-
s = size(u)
9-
if dim == 1
10-
lower = zeros(T, s[2])
11-
upper = deepcopy(lower)
12-
for i in 1:(s[2])
13-
tmp = A[i]*u[:,i]
14-
lower[i], upper[i] = (tmp.l, tmp.r)
15-
end
16-
elseif dim == 2
17-
lower = zeros(T, s[1])
18-
upper = deepcopy(lower)
19-
for i in 1:(s[1])
20-
tmp = A[i]*u[i,:]
21-
lower[i], upper[i] = (tmp.l, tmp.r)
4+
5+
@noinline function _slice_rmul!(u_temp::AbstractArray{T,N}, A::AbstractDiffEqLinearOperator, u::AbstractArray{T,N}, dim::Int, pre, post) where {T,N}
6+
for J in CartesianIndices(post)
7+
for I in CartesianIndices(pre)
8+
u_temp[I, :, J] = A*u[I, :, J]
229
end
23-
elseif dim == 3
24-
throw("The 3 dimensional Method should be being called, not this one. Check dispatch.")
25-
else
26-
throw("Dim greater than 3 not supported!")
2710
end
28-
return lower, upper
11+
u_temp
2912
end
3013

14+
function slice_rmul(A::AbstractDiffEqLinearOperator, u::AbstractArray{T,N}, dim::Int) where {T,N}
15+
u_temp = similar(u)
16+
pre = axes(u)[1:dim-1]
17+
post = axes(u)[dim+1:end]
18+
_slice_rmul!(u_temp, A, u, dim, pre, post)
19+
return u_temp
20+
end
3121

32-
@inline function slicemul(A::Array{B,2}, u::AbstractArray{T, 3}, dim::Integer) where {T, B<:AtomicBC{T}}
33-
s = size(u)
34-
if dim == 1
35-
lower = zeros(T, s[2], s[3])
36-
upper = deepcopy(lower)
37-
for j in 1:s[3]
38-
for i in 1:s[2]
39-
tmp = A[i,j]*u[:,i,j]
40-
lower[i,j], upper[i,j] = (tmp.l, tmp.r)
41-
end
42-
end
43-
elseif dim == 2
44-
lower = zeros(T, s[1], s[3])
45-
upper = deepcopy(lower)
46-
for j in 1:s[3]
47-
for i in 1:s[1]
48-
tmp = A[i,j]*u[i,:,j]
49-
lower[i,j], upper[i,j] = (tmp.l, tmp.r)
50-
end
51-
end
52-
elseif dim == 3
53-
lower = zeros(T, s[1], s[2])
54-
upper = deepcopy(lower)
55-
for j in 1:s[2]
56-
for i in 1:s[1]
57-
tmp = A[i,j]*u[i,j,:]
58-
lower[i,j], upper[i,j] = (tmp.l, tmp.r)
59-
end
22+
@noinline function _slice_rmul!(lower::Array{T, M}, upper::Array{T, M}, A::AbstractArray{B,M}, u::AbstractArray{T,N}, dim::Int, pre, post) where {T,B,N,M}
23+
for J in CartesianIndices(post)
24+
for I in CartesianIndices(pre)
25+
tmp = A[I,J]*u[I, :, J]
26+
lower[I,J], upper[I,J] = tmp.l, tmp.r
6027
end
61-
else
62-
throw("Dim greater than 3 not supported!")
6328
end
64-
return lower, upper
29+
return (lower, upper)
6530
end
6631

32+
function slice_rmul(A::AbstractArray{B,M}, u::AbstractArray{T,N}, dim::Int) where {T, B, N,M}
33+
lower = zeros(T,perpsize(u,dim))
34+
upper = zeros(T,perpsize(u,dim))
35+
pre = axes(u)[1:dim-1]
36+
post = axes(u)[dim+1:end]
37+
_slice_rmul!(lower, upper, A, u, dim, pre, post)
38+
return (lower, upper)
39+
end
40+
41+
"""
42+
slicemul is the only limitation on the BCs here being used up to arbitrary dimension, an N dimensional implementation is needed.
43+
"""
6744

6845
struct MultiDimDirectionalBC{T<:Number, B<:AtomicBC{T}, D, N, M} <: MultiDimensionalBC{T, N}
6946
BCs::Array{B,M} #dimension M=N-1 array of BCs to extend dimension D
@@ -97,13 +74,13 @@ The order is a required argument in this case.
9774
9875
where dx, dy, and dz are vectors of grid steps.
9976
"""
100-
MultiDimBC(BC::Array{B,N}, dim::Integer) where {N, B} = MultiDimDirectionalBC{gettype(BC[1]), B, dim, N+1, N}(BC)
77+
MultiDimBC(BC::Array{B,N}, dim::Integer) where {N, B<:AtomicBC} = MultiDimDirectionalBC{gettype(BC[1]), B, dim, N+1, N}(BC)
10178
#s should be size of the domain
102-
MultiDimBC(BC::B, s, dim::Integer) where {B} = MultiDimDirectionalBC{gettype(BC), B, dim, length(s), length(s)-1}(fill(BC, s[setdiff(1:length(s), dim)]))
79+
MultiDimBC(BC::B, s, dim::Integer) where {B<:AtomicBC} = MultiDimDirectionalBC{gettype(BC), B, dim, length(s), length(s)-1}(fill(BC, s[setdiff(1:length(s), dim)]))
10380

10481
#Extra constructor to make a set of BC operators that extend an atomic BC Operator to the whole domain
10582
#Only valid in the uniform grid case!
106-
MultiDimBC(BC::B, s) where {B} = Tuple([MultiDimDirectionalBC{gettype(BC), B, dim, length(s), length(s)-1}(fill(BC, s[setdiff(1:length(s), dim)])) for dim in 1:length(s)])
83+
MultiDimBC(BC::B, s) where {B<:AtomicBC} = Tuple([MultiDimDirectionalBC{gettype(BC), B, dim, length(s), length(s)-1}(fill(BC, s[setdiff(1:length(s), dim)])) for dim in 1:length(s)])
10784

10885
# Additional constructors for cases when the BC is the same for all boundarties
10986

@@ -253,7 +230,7 @@ function compose(BCs...)
253230
end
254231
BCs = BCs[sortperm([Ds...])]
255232

256-
ComposedMultiDimBC{T, Union{eltype.(BCs)...}, N,N-1}([condition.BC for condition in BCs])
233+
ComposedMultiDimBC{T, Union{eltype.(BC.BCs for BC in BCs)...}, N,N-1}([condition.BCs for condition in BCs])
257234
end
258235

259236
"""
@@ -271,11 +248,11 @@ getboundarytype(Q::MultiDimDirectionalBC{T, B, D, N, K}) where {T, B, D, N, K} =
271248
Base.ndims(Q::MultiDimensionalBC{T,N}) where {T,N} = N
272249

273250
function Base.:*(Q::MultiDimDirectionalBC{T, B, D, N, K}, u::AbstractArray{T, N}) where {T, B, D, N, K}
274-
lower, upper = slicemul(Q.BCs, u, D)
251+
lower, upper = slice_rmul(Q.BCs, u, D)
275252
return BoundaryPaddedArray{T, D, N, K, typeof(u), typeof(lower)}(lower, upper, u)
276253
end
277254

278255
function Base.:*(Q::ComposedMultiDimBC{T, B, N, K}, u::AbstractArray{T, N}) where {T, B, N, K}
279-
out = slicemul.(Q.BCs, fill(u, N), 1:N)
256+
out = slice_rmul.(Q.BCs, fill(u, N), 1:N)
280257
return ComposedBoundaryPaddedArray{T, N, K, typeof(u), typeof(out[1][1])}([A[1] for A in out], [A[2] for A in out], u)
281258
end

0 commit comments

Comments
 (0)