-
Notifications
You must be signed in to change notification settings - Fork 5
/
03_finite_differences.jl
144 lines (121 loc) · 3.26 KB
/
03_finite_differences.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
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
using PyPlot
using LinearAlgebra
using SparseArrays
function laplacian_1d(n)
# Use `Matrix(laplacian_1d(n))` to print the output of this function in a
# readable form
return (n+1)^2 * spdiagm(
-1 => fill( 1.0,n-1), # subdiagonal
0 => fill(-2.0,n), # diagonal
1 => fill( 1.0,n-1) # superdiagonal
)
end
function solve_poisson_1d(f)
n = length(f)
Δ = laplacian_1d(n)
return -Δ\f
end
function example_1d()
n = 4
x = LinRange(0,1,n+2)[2:end-1]
f = x -> π^2*sin(π*x)
uref = x -> sin(π*x)
u = solve_poisson_1d(f.(x))
clf()
xx = LinRange(0,1,1000)
plot(xx,uref.(xx), "k-", label="exact solution")
plot([0;x;1],[0;u;0], label="FD solution")
legend(frameon=false)
xlabel(L"x")
ylabel(L"u(x)")
display(gcf())
end
function convergence_1d()
# Define problem and solution
f = x -> π^2 * sin(π*x)
u = x -> sin(π*x)
# Compute errors
n = 2 .^ (1:15)
error = [begin
x = LinRange(0,1,n+2)[2:end-1]
ũ = solve_poisson_1d(f.(x))
norm(ũ .- u.(x), 2)/sqrt(n+1)
end for n in n]
# Plot
clf()
loglog(n, error, label=L"\|u - u_n\|_{2,n}")
loglog(n, n.^-2, "k--", label=L"O(n^{-2})")
xlabel(L"n")
legend(frameon=false)
display(gcf())
end
function laplacian_2d(n)
Δ = laplacian_1d(n)
Id = sparse(I,n,n) # n x n identity matrix
return kron(Id,Δ) + kron(Δ,Id)
end
function solve_poisson_2d(f)
@assert size(f,1) == size(f,2)
n = size(f,1)
Δ = laplacian_2d(n)
return reshape(-Δ\vec(f), (n,n))
end
function example_2d()
n = 100
x = LinRange(0,1,n+2)[2:end-1]
f = (x1,x2)->x1*x2
u = solve_poisson_2d(f.(x,x'))
clf()
imshow(u, extent=(0,1,0,1), origin="bottom left")
colorbar()
display(gcf())
end
function convergence_2d()
# Define problem and solution
f = (x1,x2) -> 5*π^2 * sin(π*x1) * sin(2π*x2)
u = (x1,x2) -> sin(π*x1) * sin(2π*x2)
# Compute errors
n = 2 .^ (1:9)
error = [begin
x = LinRange(0,1,n+2)[2:end-1]
ũ = solve_poisson_2d(f.(x,x'))
norm(ũ .- u.(x,x'), 2)/(n+1)
end for n in n]
# Plot
clf()
loglog(n, error, label=L"\|u - u_n\|_{2,n}")
loglog(n, 2e0*n.^-2, "k--", label=L"O(n^{-2})")
xlabel(L"n")
legend(frameon=false)
display(gcf())
end
function laplacian_3d(n)
Δ = laplacian_1d(n)
Id = sparse(I,n,n) # n x n identity matrix
return kron(Id,Id,Δ) + kron(Id,Δ,Id) + kron(Δ,Id,Id)
end
function solve_poisson_3d(f)
@assert size(f,1) == size(f,2) == size(f,3)
n = size(f,1)
Δ = laplacian_3d(n)
return reshape(-Δ\vec(f), (n,n,n))
end
function convergence_3d()
# Define problem and solution
f = (x1,x2,x3) -> 3*π^2 * sin(π*x1) * sin(π*x2) * sin(π*x3)
u = (x1,x2,x3) -> sin(π*x1) * sin(π*x2) * sin(π*x3)
# Compute errors
n = 2 .^ (1:5)
error = [begin
x = LinRange(0,1,n+2)[2:end-1]
ũ = solve_poisson_3d(f.(x,x',reshape(x,(1,1,n))))
norm(ũ .- u.(x,x',reshape(x,(1,1,n))), 2)/(n+1)^(3/2)
end for n in n]
# Plot
clf()
loglog(n, error, label=L"\|u - u_n\|_{2,n}")
loglog(n, 5e-1*n.^-2, "k--", label=L"O(n^{-2})")
xlabel(L"n")
legend(frameon=false)
display(gcf())
end