@@ -54,42 +54,60 @@ struct ComposedMultiDimBC{T, B<:AtomicBC{T}, N,M} <: MultiDimensionalBC{T, N}
5454 BCs:: Vector{Array{B, M}}
5555end
5656
57- struct PartiallyComposedMultiDimBC{T,B<: MultiDimDirectionalBC ,N,L } <: MultiDimensionalBC{T,N}
57+ struct PartiallyComposedMultiDimBC{T,B<: Union{ MultiDimDirectionalBC, Nothing} ,N, is_extended } <: MultiDimensionalBC{T,N}
5858 BCs:: Vector{B}
5959end
6060
61- function Base.:+ (Q1:: MultiDimDirectionalBC{T,B1,D1,N,M} , Q2:: MultiDimDirectionalBC{T,B2,D2,N,M} ) where {T,B1, B2,D1,D2,N,M}
62- @assert D1 != D2 " BCs should all extend along a unique axis"
63- return PartiallyComposedMultiDimBC {T,Union{typeof(Q1),typeof(Q2)}, N,2} (Array[Q1,Q2])
64- end
61+ numextended
6562
66- function Base.:+ (Q1:: MultiDimDirectionalBC{T,B1,D1,2,1} , Q2:: MultiDimDirectionalBC{T,B2,D2,2,1} ) where {T,B1,B2,D1,D2}
67- return compose (Q1,Q2)
68- end
6963
70- function Base.:+ (Q:: PartiallyComposedMultiDimBC{T,B,N,L} , Q1:: MultiDimDirectionalBC ) where {T,B,N,M,L}
71- new_BCs = vcat (Q. BCs,Q1)
72- if L+ 1 == N
73- return compose (new_BCs... )
74- elseif ! (getaxis (Q1) in getaxis .(Q. BCs))
75- return PartiallyComposedMultiDimBC {T,eltype(new_BCs), N,L-1} (new_BCs)
76- else
77- throw (" BCs should all extend along a unique axis" )
64+ function Base. _: + (BCs:: MultiDimDirectionalBC{T} ...) where T
65+ D = getaxis .(BCs)
66+ BCs = BCs[sortperm ([D... ])]
67+ B = typeof .(BCs)
68+ dimensionalities = ndims .(BCs)
69+ for n in dimensionalities[2 : end ]
70+ @assert dimensionalites[1 ] == n " There are "
71+
72+ for d in D
73+ @assert length (setdiff (D, d)) == (N- 1 ) " There are multiple boundary conditions that extend along $d - make sure every dimension has a unique extension"
7874 end
75+ is_extended = falses (length (ndims (BCs[1 ]))
76+ is_extended[D] .= true
77+ A = Vector {Union{B..., Nothing}} (undef, ndims (BCs[1 ]))
78+ A[! is_extended] .= Nothing ()
79+ for (i,BC) in enumerate (BCs)
80+ A[is_extended][i] = BC
81+ end
82+ return PartiallyComposedMultiDimBC {T, eltype(A), N, is_extended} (A)
83+ end
84+
85+
86+ function Base.:+ (Q:: PartiallyComposedMultiDimBC{T,B,N,L} , Q1:: MultiDimDirectionalBC{T, B2, D, N, M} ) where {T,D, B1, B2,N,M,L}
87+ new_BCs = Q. BCs
88+ new_BCs[D] = Q1
89+ is_extended = L
90+ is_extended[D] = true
91+ @assert ! (getaxis (Q1) in getaxis .(Q. BCs)) " BCs should all extend along a unique axis"
92+ return PartiallyComposedMultiDimBC {T,eltype(new_BCs), N,is_extended} (new_BCs)
93+
7994end
8095
8196Base.:+ (Q1:: MultiDimDirectionalBC , Q:: PartiallyComposedMultiDimBC ) = + (Q,Q1)
8297
83- function Base.:+ (Q1:: PartiallyComposedMultiDimBC{T,B1,N,L1} Q2:: PartiallyComposedMultiDimBC {T,B2,N,L2) where {T,B1,B2,N,L1,L2}
84- new_BCs = vcat (Q1. BCs, Q2. BCs)
85- if L1 + L2 < N
86- @assert length (setdiff (1 : N, getaxis .(new_BCs))) == (N- L1- L2) " BCs should all extend along a unique axis"
87- return PartiallyComposedMultiDimBC {T,Union{B1,B2}, N, L1+ L2} (new_BCs)
88- elseif L1+ L2 == N
89- return compose (new_BCs... )
90- else
91- throw (" Too many supplied BCs for the number of dimensions" )
92- end
98+ function Base.:+ (Q1:: PartiallyComposedMultiDimBC{T,B1,N,L1} Q2:: PartiallyComposedMultiDimBC{T,B2,N,L2} ) where {T,B1,B2,N,L1,L2}
99+ new_BCs = deepcopy (Q1. BCs)
100+ Lnew = L1 .| L2
101+ for (i,q) in enumerate (Q2. BCs)
102+ if q <: MultiDimensionalBC
103+ if new_BCs[i] <: Nothing
104+ new_BCs[i] = q
105+ else
106+ throw (" BCs should all extend along a unique axis" )
107+ end
108+ end
109+ end
110+ return PartiallyComposedMultiDimBC {T,Union{B1,B2}, N, Lnew} (new_BCs)
93111end
94112
95113"""
@@ -121,6 +139,11 @@ For Neumann0BC, please use
121139where T is the element type of the domain to be extended
122140"""
123141struct MultiDimBC{N} end
142+ struct NeumannBC{N} end
143+ struct Neumann0BC{N} end
144+ struct DirichletBC{N} end
145+ struct Dirichlet0BC{N} end
146+
124147MultiDimBC {dim} (BC:: Array{B,N} ) where {N, B<: AtomicBC , dim} = MultiDimDirectionalBC {gettype(BC[1]), B, dim, N+1, N} (BC)
125148# s should be size of the domain
126149MultiDimBC {dim} (BC:: B , s) where {B<: AtomicBC , dim} = MultiDimDirectionalBC {gettype(BC), B, dim, length(s), length(s)-1} (fill (BC, s[setdiff (1 : length (s), dim)]))
@@ -129,17 +152,26 @@ MultiDimBC{dim}(BC::B, s) where {B<:AtomicBC, dim} = MultiDimDirectionalBC{gett
129152# Only valid in the uniform grid case!
130153MultiDimBC (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)])
131154
132- # Additional constructors for cases when the BC is the same for all boundarties
133-
134- PeriodicBC {T} ( s) where T = MultiDimBC (PeriodicBC {T} ( ), s)
155+ # Additional constructors for cases when the BC is the same for all boundarties
156+ PeriodicBC {dim} (T,s) where T = MultiDimBC {dim} ( PeriodicBC (T), s)
157+ PeriodicBC (T, s) where T = MultiDimBC (PeriodicBC (T ), s)
135158
159+ NeumannBC {dim} (α:: NTuple{2,T} , dx, order, s) where T = RobinBC {dim} ((zero (T), one (T), α[1 ]), (zero (T), one (T), α[2 ]), dx, order, s)
136160NeumannBC (α:: NTuple{2,T} , dxyz, order, s) where T = RobinBC ((zero (T), one (T), α[1 ]), (zero (T), one (T), α[2 ]), dxyz, order, s)
161+
162+ DirichletBC {dim} (αl:: T , αr:: T , s) where T = RobinBC {dim} ((one (T), zero (T), αl), (one (T), zero (T), αr), [ones (T, si) for si in s], 2.0 , s)
137163DirichletBC (α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)
138164
165+ Dirichlet0BC {dim} (T:: Type , s) = DirichletBC {dim} (zero (T), zero (T), s)
139166Dirichlet0BC (T:: Type , s) = DirichletBC (zero (T), zero (T), s)
167+
168+ Neumann0BC {dim} (T:: Type , dx, order, s) = NeumannBC {dim} ((zero (T), zero (T)), dx, order, s)
140169Neumann0BC (T:: Type , dxyz, order, s) = NeumannBC ((zero (T), zero (T)), dxyz, order, s)
141170
171+ RobinBC {dim} (l:: NTuple{3,T} , r:: NTuple{3,T} , dx, order, s) where {T} = MultiDimBC {dim} (RobinBC (l, r, dx, order), s)
142172RobinBC (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)])
173+
174+ GeneralBC {dim} (αl:: AbstractVector{T} , αr:: AbstractVector{T} , dx, order, s) where {T} = MultiDimBC {dim} (GeneralBC (αl, αr, dx, order), s)
143175GeneralBC (α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)])
144176
145177
@@ -157,7 +189,7 @@ Creates a ComposedMultiDimBC operator, Q, that extends every boundary when appli
157189
158190Qx Qy and Qz can be passed in any order, as long as there is exactly one BC operator that extends each dimension.
159191"""
160- function compose (BCs... )
192+ function compose (BCs:: MultiDimDirectionalBC ... )
161193 T = gettype (BCs[1 ])
162194 N = ndims (BCs[1 ])
163195 Ds = getaxis .(BCs)
@@ -170,6 +202,8 @@ function compose(BCs...)
170202 ComposedMultiDimBC {T, Union{eltype.(BC.BCs for BC in BCs)...}, N,N-1} ([condition. BCs for condition in BCs])
171203end
172204
205+ Base.:+ (BCs:: MultiDimDirectionalBC... ) = compose (BCs... )
206+
173207"""
174208Qx, Qy,... = decompose(Q::ComposedMultiDimBC{T,N,M})
175209
@@ -198,5 +232,18 @@ function Base.:*(Q::ComposedMultiDimBC{T, B, N, K}, u::AbstractArray{T, N}) wher
198232 return ComposedBoundaryPaddedArray {T, N, K, typeof(u), typeof(out[1][1])} ([A[1 ] for A in out], [A[2 ] for A in out], u)
199233end
200234
201- function Base.:* (Q:: PartiallyComposedMultiDimBC , u:: AbstractArray{T,N} where {T,N}
202- return Tuple ([MultiDimDirectionalBC
235+
236+
237+ function Base.:* (Q:: PartiallyComposedMultiDimBC{T,B,N,is_extended} , u:: AbstractArray{T,N} where {T,N}
238+ lower = Vector {Union{Array{T,N-1}, Nothing}} (undef, N)
239+ upper = Vector {Union{Array{T,N-1}, Nothing}} (undef, N)
240+ for (i,q) in Q. BCs
241+ if ! (q <: Nothing )
242+ lower[i], upper[i] = slice_rmul (q, u)
243+ else
244+ lower[i] = Nothing ()
245+ upper[i] = Nothing ()
246+ end
247+ end
248+ return PartiallyComposedBoundaryPaddedArray {} (lower,upper,u)
249+ end
0 commit comments