-
Notifications
You must be signed in to change notification settings - Fork 11
/
Copy pathnlsolver.m
105 lines (84 loc) · 1.54 KB
/
nlsolver.m
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
%Demo non-linear Poisson solver
% we are solving:
% d^2phi/(dh^2) = -rho/eps0*(ni-n0*exp((phi-phi0)/kTe))
% with phi=-5, 5 on left and right boundary
% See http://www.particleincell.com/2012/nonlinear-poisson-solver/
% for additional info
%clear screen
clc
%constants
EPS0 = 8.85418782e-12;
Q = 1.60217646e-19;
%setup coefficients
den0=1e16;
phi0=0;
kTe=5;
%precomputed values
lambda_D = sqrt(EPS0*kTe/(den0*Q)); %for kTe in eV
dh = lambda_D; %cell spacing
C = -Q/EPS0*dh*dh;
%setup matrixes
nn=15; %number of nodes
A=zeros(nn,nn);
fixed_node = zeros(nn,1);
b0=zeros(nn,1);
%left boundary
A(1,1)=1;
b0(1)=-5;
fixed_node(1)=1;
%right boundary
A(nn,nn)=1;
b0(nn)=5;
fixed_node(nn)=1;
%internal nodes
for n=2:nn-1
%FD stencil
A(n,n-1)=1;
A(n,n)=-2;
A(n,n+1)=1;
fixed_node(n)=false;
b0(n)=C*den0;
end
%initial values
bx = zeros(nn,1);
P = zeros(nn,1);
J = zeros(nn,nn);
x = zeros(nn,1);
y = zeros(nn,1);
%--- Newton Solver ----
for it=1:20
%1) compute bx
for n=1:nn
if (fixed_node(n))
bx(n)=0;
else
bx(n) = -C*den0*exp((x(n)-phi0)/kTe);
end
end
%2) b=b0+bx
b = b0 + bx;
%3) F=Ax-b
F = A*x-b;
%4) compute P=dbx(i)/dx(j), used in computing J
for n=1:nn
if (fixed_node(n))
P(n)=0;
else
P(n) = -C*den0*exp((x(n)-phi0)/kTe)/kTe;
end
end
%5) J=df(i)/dx(j), J=A+diag(dbx(i)/dx(j))
J = A - diag(P);
%6) Solve Jy=F
y = J\F;
%7) update x
x = x - y;
%8) compute norm;
l2 = norm(y);
if (l2<1e-6)
disp(sprintf("Converged in %d iterations with norm %g\n",it,l2));
break;
end
end
disp(x');
plot(x);