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

Commit 8c6a061

Browse files
committed
Added Boundary condition operators, up to any order of accuracy
1 parent 734e5b7 commit 8c6a061

File tree

1 file changed

+151
-0
lines changed

1 file changed

+151
-0
lines changed
Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
abstract type AbstractBC{T} end
2+
3+
# robin, general, and in general neumann BCs are all affine. neumann0 is not however; is a specialization needed?
4+
abstract type AffineBC{T,V} <: AbstractBC{T} end
5+
6+
struct DirichletBC{T} <: AbstractBC{T}
7+
l::T
8+
r::T
9+
end
10+
11+
struct NeumannBC{T, V<:AbstractArray{T}} <: AffineBC{T,V}
12+
a_l::V
13+
b_l::T
14+
a_r::V
15+
b_r::T
16+
function NeumannBC(l::T, r::T, dx::AbstractArray{T}, order::T = one(T)) where {T,V}
17+
s = calculate_weights(1, zero(T), zero(T):order) #generate derivative coefficients about the boundary of required approximation order
18+
19+
a_l = -dx_l.*s[2:end]./s[1]
20+
a_r = -dx_r.*s[end:-1:2]./s[1]
21+
22+
b_l = dx_l.*l./s[1]
23+
b_r = dx_r.*l./s[1]
24+
25+
return new{T, typeof(a_l)}(a_l, b_l, a_r, b_r)
26+
end
27+
end
28+
29+
struct PeriodicBC{T} <: AbstractBC{T}
30+
31+
end
32+
33+
"""
34+
Implements a robin boundary condition operator Q that acts on a vector to give an extended vector as a result
35+
Referring to (https://github.com/JuliaDiffEq/DiffEqOperators.jl/files/3267835/ghost_node.pdf)
36+
37+
the variables in correspond to al*u(0) + bl*u'(0) = cl
38+
39+
40+
Write vector b̄_1 as a vertical concatanation with b0 and the rest of the elements of b̄_1, denoted b̄`_1, the same with ū into u0 and ū`. b̄` = fill(β/Δx, length(stencil)-1)
41+
Pull out the product of u0 and b0 from the dot product. The stencil used to approximate u` is denoted s. b0 = α+(β/Δx)*s[1]
42+
Rearrange terms to find a general formula for u0:= -b̄`_1̇⋅ū`/b0 + γ/b0 , the robin coefficients and Δx.
43+
The non identity part of Qa is qa:= -b`_1/b0 = -β.*s[2:end]/(α+β*s[1]/Δx). The constant part is Qb = γ/(α+β*s[1]/Δx)
44+
do the same at the other boundary (amounts to a flip in s.)
45+
"""
46+
47+
# For condition, the variables correspond to al*u(0) + bl*u'(0) = cl
48+
# this should not break
49+
struct RobinBC{T, V<:AbstractVector{T}} <: AffineBC{T,V}
50+
a_l::V
51+
b_l::T
52+
a_r::V
53+
b_r::T
54+
function RobinBC(l::AbstractArray{T}, r::AbstractArray{T}, dx::AbstractArray{T}, order::T = one(T)) where {T,V}
55+
cl, al, bl = l
56+
cr, ar, br = r
57+
dx_l, dx_r = dx
58+
59+
s = calculate_weights(1, zero(T), zero(T):order) #generate derivative coefficients about the boundary of required approximation order
60+
61+
a_l = -bl.*s[2:end]./(al .+ bl*s[1]./dx_l)
62+
a_r = -br.*s[end:-1:2]./(ar .+ br*s[1]./dx_r)
63+
64+
b_l = cl/(al+bl*s[1]/dx_l)
65+
b_r = cr/(ar+br*s[1]/dx_r)
66+
67+
return new{T, typeof(a_l)}(a_l, b_l, a_r, b_r)
68+
end
69+
end
70+
71+
"""
72+
Implements a generalization of the Robin boundary condition, where α is a vector of coefficients.
73+
Represents a condition of the form α[1] + α[2]u[0] + α[3]u'[0] + α[4]u''[0]+... = 0
74+
Implemented in an analogous way to the RobinBC
75+
"""
76+
#If you know a more correct name for this kind of BC, please post an issue/PR
77+
struct GeneralBC{T, V<:AbstractVector{T}} <:AffineBC{T,V}
78+
a_l::V
79+
b_l::T
80+
a_r::V
81+
b_r::T
82+
function GeneralBC{T,V}(αl::AbstractArray{T}, αr::AbstractArray{T}, dx::AbstractArray{T}, order::T = one(T)) where {T,V<:AbstractArray}
83+
dx_l, dx_r = dx
84+
nl = length(αl)
85+
nr = length(αr)
86+
S_l = zeros(T, (nl-2, order+nl-2))
87+
S_r = zeros(T, (nr-2, order+nr-2))
88+
89+
for i in 1:(nl-2)
90+
S_l[i,:] = [transpose(calculate_weights(i, zero(T), zero(T):(order+i))) transpose(zeros(T, nl-2-i))] #am unsure if the length of the dummy_x is correct here
91+
end
92+
for i in 1:(nr-2)
93+
S_r[i,:] = [transpose(calculate_weights(i, zero(T), zero(T):(order+i))) transpose(zeros(T, nr-2-i))]
94+
end
95+
s0_l = S_l[:,1] ; Sl = S_l[2:end,:]
96+
s0_r = S_r[:,1] ; Sr = S_r[2:end,:]
97+
98+
denoml = αl[2] .+ αl[3:end] s0_l
99+
denomr = αr[2] .+ αr[3:end] s0_r
100+
101+
a_l = -transpose(αl) Sl ./denoml
102+
a_r = -transpose(αr) Sr ./denomr
103+
104+
b_l = -αl[1]/denoml
105+
b_r = -αr[1]/denomr
106+
new{T, V}(a_l,b_l,reverse!(a_r),b_r)
107+
end
108+
end
109+
110+
# other acceptable argument signatures
111+
RobinBC(al::T, bl::T, cl::T, dx_l::T, ar::T, br::T, cr::T, dx_r::T) where T = RobinBC([al,bl,cl], [ar, br, cr], [dx_l, dx_r])
112+
RobinBC(al::T, bl::T, cl::T, dx_l::T, ar::T, br::T, cr::T, dx_r::T, order::T) where T = RobinBC([al,bl,cl], [ar, br, cr], [dx_l, dx_r], order)
113+
114+
NeumannBC(l::T, dx_l::T, r::T, dx_r::T) where T = NeumannBC(l, r, [dx_l,dx_r])
115+
NeumannBC(l::T, dx_l::T, r::T, dx_r::T, order::T) where T = NeumannBC(l, r, [dx_l,dx_r], order)
116+
# this is 'boundary padded vector' as opposed to 'boundary padded array' to distinguish it from the n dimensional implementation that will eventually be neeeded
117+
struct BoundaryPaddedVector{T,T2 <: AbstractVector{T}}
118+
l::T
119+
r::T
120+
u::T2
121+
end
122+
123+
124+
Base.:*(Q::DirichletBC, u) = BoundaryPaddedVector(Q.l,Q.r,u)
125+
Base.:*(Q::PeriodicBC, u) = BoundaryPaddedVector(u[end], u[1], u)
126+
Base.:*(Q::AffineBC, u) = BoundaryPaddedVector(Q.a_l u[1:length(Q.a_l)] + Q.b_l, Q.a_r u[(end-length(Q.a_r)+1):end] + Q.b_r, u)
127+
128+
Base.size(Q::AbstractBC) = (Inf, Inf) #Is this nessecary?
129+
Base.length(Q::BoundaryPaddedVector) = length(Q.u) + 2
130+
Base.lastindex(Q::BoundaryPaddedVector) = Base.length(Q)
131+
132+
function Base.getindex(Q::BoundaryPaddedVector,i)
133+
@show i
134+
if i == 1
135+
return Q.l
136+
elseif i == length(Q)
137+
return Q.r
138+
else
139+
return Q.u[i-1]
140+
end
141+
end
142+
143+
function LinearAlgebra.Array(Q::AffineBC, N::Int)
144+
Q_L = [transpose(Q.a_l) transpose(zeros(N-length(Q.a_l))); Diagonal(ones(N)); transpose(zeros(N-length(Q.a_r))) transpose(Q.a_r)]
145+
Q_b = [Q.b_l; zeros(N); Q.b_r]
146+
return (Q_L, Q_b)
147+
end
148+
149+
function LinearAlgebra.Array(Q::BoundaryPaddedVector)
150+
return [Q.l; Q.u; Q.r]
151+
end

0 commit comments

Comments
 (0)