-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathlinear_solver.jl
109 lines (103 loc) · 4.89 KB
/
linear_solver.jl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
struct Stencil end
struct LinearSolver{D, T <: Tuple}
n :: NTuple{D,Int64}
Δ :: NTuple{D, Vector{Float64}}
δ :: NTuple{D, Vector{Float64}}
h :: Float64
A :: SparseMatrixCSC{Float64, Int64}
b :: Vector{Float64}
u :: Vector{Float64}
rhs :: Vector{Float64}
dof :: Matrix{Int64}
bcs :: T
end
const Forward = Val{:+}
const Reverse = Val{:-}
function solve!(ps::LinearSolver{D, T}, ρ) where {D, T}
@inbounds for i in eachindex(ρ)
ps.rhs[i] = ps.b[i] - ρ[i] * ps.h^2 # assume uniform mesh in all directions
end
ps.u .= (ps.A \ ps.rhs)
return nothing
end
@inline function fixed!(ps::LinearSolver{2, T}, value, i, j) where {T}
dof = ps.dof[i,j]
@assert ps.b[dof] == 0. "You are going to reset a degree of freedom that has b[i] != 0"
ps.A[dof, :] .= 0.
ps.A[dof, dof] = 1.
ps.b[dof] = value
return nothing
end
# Cartesian coordinate system
@inline function cartesian!(A::SparseMatrixCSC{Float64, Int64}, bc::Stencil, dir::Forward, i, j)
A[i, i] += 1.; A[i, j] -= 1.
end
@inline function cartesian!(A::SparseMatrixCSC{Float64, Int64}, bc::Stencil, dir::Reverse, i, j)
A[i, i] -= 1.; A[i, j] += 1.
end
@inline function cartesian!(A::SparseMatrixCSC{Float64, Int64}, bc::PeriodicBC, dir::Forward, i, _, k)
A[i, i] += 1.; A[i, k] -= 1.
end
@inline function cartesian!(A::SparseMatrixCSC{Float64, Int64}, bc::PeriodicBC, dir::Reverse, i, _, k)
A[i, i] -= 1.; A[i, k] += 1.
end
@inline function cartesian!(b::Vector{Float64}, bc::PeriodicBC, dir::Forward, i) end
@inline function cartesian!(b::Vector{Float64}, bc::PeriodicBC, dir::Reverse, i) end
@inline function cartesian!(A::SparseMatrixCSC{Float64, Int64}, bc::NeumannBC, dir::Forward, i, j, _) end
@inline function cartesian!(A::SparseMatrixCSC{Float64, Int64}, bc::NeumannBC, dir::Reverse, i, j, _) end
@inline function cartesian!(b::Vector{Float64}, bc::NeumannBC, dir::Forward, i) b[i] += bc.value end
@inline function cartesian!(b::Vector{Float64}, bc::NeumannBC, dir::Reverse, i) b[i] -= bc.value end
@inline function cartesian!(A::SparseMatrixCSC{Float64, Int64}, bc::DirichletBC, dir::Forward, i, j, _)
A[i, i] += 3.; A[i, j] -= 1/3
end
@inline function cartesian!(A::SparseMatrixCSC{Float64, Int64}, bc::DirichletBC, dir::Reverse, i, j, _)
A[i, i] -= 3.; A[i, j] += 1/3
end
@inline function cartesian!(b::Vector{Float64}, bc::DirichletBC, dir::Forward, i)
b[i] += (8/3)bc.value
end
@inline function cartesian!(b::Vector{Float64}, bc::DirichletBC, dir::Reverse, i)
b[i] -= (8/3)bc.value
end
# Cylindrical coordinate coordinate system
@inline function radial!(A::SparseMatrixCSC{Float64, Int64}, bc::Stencil, dir::Forward, α, i, j)
A[i, i] += α; A[i, j] -= α
end
@inline function radial!(A::SparseMatrixCSC{Float64, Int64}, bc::Stencil, dir::Reverse, α, i, j)
A[i, i] -= α; A[i, j] += α
end
@inline function radial!(A::SparseMatrixCSC{Float64, Int64}, bc::NeumannBC, dir::Forward, α, i, j, _) end
@inline function radial!(A::SparseMatrixCSC{Float64, Int64}, bc::NeumannBC, dir::Reverse, α, i, j, _) end
@inline function radial!(b::Vector{Float64}, bc::NeumannBC, dir::Forward, α, i) b[i] += α*bc.value end
@inline function radial!(b::Vector{Float64}, bc::NeumannBC, dir::Reverse, α, i) b[i] -= α*bc.value end
@inline function radial!(A::SparseMatrixCSC{Float64, Int64}, bc::DirichletBC, dir::Forward, α, i, j, _)
A[i, i] += 3.0α; A[i, j] -= α/3.0
end
@inline function radial!(A::SparseMatrixCSC{Float64, Int64}, bc::DirichletBC, dir::Reverse, α, i, j, _)
A[i, i] -= 3.0α; A[i, j] += α/3.0
end
@inline function radial!(b::Vector{Float64}, bc::DirichletBC, dir::Forward, α, i)
b[i] += α*(8/3)bc.value
end
@inline function radial!(b::Vector{Float64}, bc::DirichletBC, dir::Reverse, α, i)
b[i] -= α*(8/3)bc.value
end
# Polar coordinate system
@inline function polar!(A::SparseMatrixCSC{Float64, Int64}, bc::Stencil, dir::Forward, α, i, j)
A[i, i] += α; A[i, j] -= α
end
@inline function polar!(A::SparseMatrixCSC{Float64, Int64}, bc::Stencil, dir::Reverse, α, i, j)
A[i, i] -= α; A[i, j] += α
end
@inline function polar!(A::SparseMatrixCSC{Float64, Int64}, bc::PeriodicBC, dir::Forward, α, i, _, k)
A[i, i] += α; A[i, k] -= α
end
@inline function polar!(A::SparseMatrixCSC{Float64, Int64}, bc::PeriodicBC, dir::Reverse, α, i, _, k)
A[i, i] -= α; A[i, k] += α
end
@inline function polar!(b::Vector{Float64}, bc::PeriodicBC, dir::Forward, α, i) end
@inline function polar!(b::Vector{Float64}, bc::PeriodicBC, dir::Reverse, α, i) end
@inline function polar!(A::SparseMatrixCSC{Float64, Int64}, bc::NeumannBC, dir::Forward, α, i, j, _) end
@inline function polar!(A::SparseMatrixCSC{Float64, Int64}, bc::NeumannBC, dir::Reverse, α, i, j, _) end
@inline function polar!(b::Vector{Float64}, bc::NeumannBC, dir::Forward, α, i) b[i] += α*bc.value end
@inline function polar!(b::Vector{Float64}, bc::NeumannBC, dir::Reverse, α, i) b[i] -= α*bc.value end