Skip to content

Commit 69cacf5

Browse files
Fabio VerboFabio Verbo
Fabio Verbo
authored and
Fabio Verbo
committed
First implementation for stencil Diff-React
0 parents  commit 69cacf5

File tree

5 files changed

+353
-0
lines changed

5 files changed

+353
-0
lines changed

diffreactstencil.m

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
function S = diffreactstencil(U, x_old, nx, ny, bnd, alpha, dxs)
2+
% DIFFREACTSTENCIL computes stencil as inner + bounds + corners
3+
4+
bndN = bnd.bndN;
5+
bndS = bnd.bndS;
6+
bndE = bnd.bndE;
7+
bndW = bnd.bndW;
8+
9+
S = zeros(size(U));
10+
11+
%% Interior grid points
12+
for j = 2:ny-1 %(int j=1; j < jend; j++) {
13+
for i = 2:nx-1 %(int i=1; i < iend; i++) {
14+
S(i,j) = -(4.0 + alpha) * U(i,j) ... % central point
15+
+ U(i-1,j) + U(i+1,j) ... % east and west
16+
+ U(i,j-1) + U(i,j+1) ... % north and south
17+
+ alpha * x_old(i,j) ...
18+
+ dxs * U(i,j) * (1.0 - U(i,j));
19+
end
20+
end
21+
% end Interior grid points
22+
23+
%% East boundary
24+
i = nx; %int i = nx - 1;
25+
for j = 2:ny-1 %(int j = 1; j < jend; j++)
26+
S(i,j) = -(4.0 + alpha) * U(i,j) ...
27+
+ U(i-1,j) + U(i,j-1) + U(i,j+1) ...
28+
+ alpha*x_old(i,j) + bndE(j) ...
29+
+ dxs * U(i,j) * (1.0 - U(i,j));
30+
end
31+
% end East boundary
32+
33+
%% West boundary
34+
i = 1; %int i = 0;
35+
for j = 2:ny-1 %(int j = 1; j < jend; j++)
36+
S(i,j) = -(4.0 + alpha) * U(i,j) ...
37+
+ U(i+1,j) + U(i,j-1) + U(i,j+1) ...
38+
+ alpha * x_old(i,j) + bndW(j) ...
39+
+ dxs * U(i,j) * (1.0 - U(i,j));
40+
end
41+
% end West boundary
42+
43+
%% North boundary, plus NE and NW corners
44+
j = ny; %int j = ny - 1;
45+
46+
% NW corner
47+
i = 1; %int i = 0; // NW corner
48+
S(i,j) = -(4.0 + alpha) * U(i,j) ...
49+
+ U(i+1,j) + U(i,j-1) ...
50+
+ alpha * x_old(i,j) + bndW(j) + bndN(i) ...
51+
+ dxs * U(i,j) * (1.0 - U(i,j));
52+
% end NW corner
53+
54+
% North boundary w/o corners
55+
for i = 2:nx-1 %(int i = 1; i < iend; i++)
56+
S(i,j) = -(4.0 + alpha) * U(i,j) ...
57+
+ U(i-1,j) + U(i+1,j) + U(i,j-1) ...
58+
+ alpha*x_old(i,j) + bndN(i) ...
59+
+ dxs * U(i,j) * (1.0 - U(i,j));
60+
end
61+
% end North boundary w/o corners
62+
63+
% NE corner
64+
i = nx; % int i = nx-1; // NE corner
65+
S(i,j) = -(4.0 + alpha) * U(i,j) ...
66+
+ U(i-1,j) + U(i,j-1) ...
67+
+ alpha * x_old(i,j) + bndE(j) + bndN(i) ...
68+
+ dxs * U(i,j) * (1.0 - U(i,j));
69+
% end NE corner
70+
71+
%% South boundary, plus SW and SE corners
72+
j = 1; % int j = 0;
73+
74+
% SW corner
75+
i = 1; % int i = 0; // SW corner
76+
S(i,j) = -(4.0 + alpha) * U(i,j) ...
77+
+ U(i+1,j) + U(i,j+1) ...
78+
+ alpha * x_old(i,j) + bndW(j) + bndS(i) ...
79+
+ dxs * U(i,j) * (1.0 - U(i,j));
80+
% end SW corner
81+
82+
% South boundary w/o corners
83+
for i = 2:nx-1 %(int i = 1; i < iend; i++)
84+
S(i,j) = -(4.0 + alpha) * U(i,j) ...
85+
+ U(i-1,j) + U(i+1,j) + U(i,j+1) ...
86+
+ alpha * x_old(i,j) + bndS(i) ...
87+
+ dxs * U(i,j) * (1.0 - U(i,j));
88+
end
89+
% end South boundary w/o corners
90+
91+
% SE corner
92+
i = nx; % int i = nx - 1; // SE corner
93+
S(i,j) = -(4.0 + alpha) * U(i,j) ...
94+
+ U(i-1,j) + U(i,j+1) ...
95+
+ alpha * x_old(i,j) + bndE(j) + bndS(i) ...
96+
+ dxs * U(i,j) * (1.0 - U(i,j));
97+
% end SW corner
98+
99+
end
100+
101+
102+
103+

diffusereact.m

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
function B = diffusereact(X, Xold, alpha, dxs)
2+
% DIFFUSEREACT computes Diffusion/Reaction using Laplacian matrix.
3+
4+
global A;
5+
6+
aI = alpha*speye(size(A));
7+
B = (A - aI)*X + alpha*Xold + dxs * (X - X.^2);
8+
end
9+

drstencil.m

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
function S = drstencil(X, Xold, nx, ny, alpha, dxs)
2+
% DRSTENCIL computes the stencil for a grid including BCs
3+
4+
X = reshape(X,nx,ny);
5+
Xold = reshape(Xold,nx,ny);
6+
S = zeros(size(X));
7+
8+
for j = 2:ny-1
9+
for i = 2:nx-1
10+
S(i,j) = -(4.0 + alpha) * X(i,j) ... % central point
11+
+ X(i-1,j) + X(i+1,j) ... % east and west
12+
+ X(i,j-1) + X(i,j+1) ... % north and south
13+
+ alpha * Xold(i,j) ...
14+
+ dxs * X(i,j) * (1.0 - X(i,j));
15+
end
16+
end
17+
18+
S = S(:);
19+
20+
end
21+
22+

reactdiff.m

Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
% REACTDIFF script for testing stencil-based CG for Diffusion/Reaction problems.
2+
%
3+
4+
%% SET PARAMS
5+
6+
nx = 64;
7+
ny = 64;
8+
assert(nx == ny, 'Grid must be square. Set nx = ny.');
9+
N = nx * ny;
10+
x0 = 0;
11+
xmax = 1;
12+
y0 = 0;
13+
ymax = 1;
14+
tlim = 0.01;
15+
tsteps = 10;
16+
17+
maxitCG = 100;
18+
tolCG = 1e-4;
19+
20+
maxitNT = 20;
21+
tolNT = 1e-8;
22+
23+
T = linspace(0, tlim, tsteps);
24+
dt = tlim/tsteps;
25+
26+
bndN = 0.00;
27+
bndS = 0.00;
28+
bndW = 0.00;
29+
bndE = 0.00;
30+
31+
bnd.bndN = bndN;
32+
bnd.bndS = bndS;
33+
bnd.bndE = bndE;
34+
bnd.bndW = bndW;
35+
36+
dx = (xmax-x0)/(nx);
37+
dy = (ymax-y0)/(ny);
38+
39+
%D = 1; % Diffusion constant
40+
%R = 1;
41+
F = 0.5; % Initial condition
42+
43+
alpha = dx^2/dt;
44+
dxs = 100 / dx^2;
45+
46+
47+
global A;
48+
A = -gallery('poisson', nx);
49+
50+
%% SET INITIAL CONDITIONS
51+
X = zeros(nx,ny);
52+
53+
% Center and radius of the circle
54+
c = [xmax-1/4, y0+1/4];
55+
r = min(c) / 2;
56+
57+
for j = 1:nx
58+
x = x0 + j*dx;
59+
for k = 1:ny
60+
p = [x, y0+k*dy];
61+
%disp(p);
62+
if norm(c-p) <= r
63+
X(j,k) = F;
64+
end
65+
end
66+
end
67+
68+
%% SET BOUNDARY CONDITIONS
69+
70+
X(1,:) = bndN;
71+
X(end,:) = bndS;
72+
X(:,1) = bndW;
73+
X(:,end) = bndE;
74+
75+
X = X(:);
76+
77+
%% RUN TIME-S
78+
79+
figure('Name',sprintf('%d x %d grid', nx, ny));
80+
81+
global f;
82+
83+
tTot = tic;
84+
85+
ts = 1;
86+
for t = T
87+
88+
fprintf('T-step %4d/%4d:\n', ts, tsteps);
89+
90+
Xold = X;
91+
imagesc(reshape(X, nx,nx)); colorbar; pause(0.5);
92+
93+
convNT = false;
94+
for k = 1:maxitNT
95+
96+
%f = @(X) drstencil(X, Xold, nx, ny, alpha, dxs);
97+
f = @(X) diffusereact(X, Xold, alpha, dxs);
98+
99+
X = f(Xold);
100+
101+
fB = norm(X);
102+
fprintf('NWT: it=%3d, ||f(B)|| = %.4e | ', k, fB);
103+
if (fB < tolNT)
104+
fprintf('Newton method has converged!\n');
105+
convNT = true;
106+
break;
107+
end
108+
109+
[dX, flg, relres, its] = stencil_pcg(f, X, tolCG, maxitCG);
110+
111+
112+
fprintf('CG: ');
113+
switch flg
114+
case 1
115+
fprintf('CG iterated %d times but did not converge.\n', maxitCG);
116+
case 2
117+
fprintf('CG preconditioner M was ill-conditioned.\n');
118+
case 3
119+
fprintf('CG stagnated.\n');
120+
case 4
121+
fprintf('CG: one of the scalar quantities is too small or too large.\n');
122+
end
123+
124+
if flg > 0
125+
break;
126+
end
127+
128+
fprintf('residual %.4e after %3d iterations.\n', relres, its);
129+
X = Xold - dX;
130+
Xold = X;
131+
%spy(reshape(dX, nx,nx))
132+
133+
end
134+
135+
imagesc(reshape(X, nx,nx)); colorbar;
136+
137+
if convNT
138+
ts = ts+1;
139+
continue;
140+
else
141+
error('Newton method FAILED to converge.');
142+
end
143+
144+
145+
146+
end
147+
148+
fprintf('-----------------------------------\n');
149+
fprintf('Simulation took %f seconds.\n', toc(tTot));
150+
151+
152+

stencil_pcg.m

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
function [x, flg, resNew, its] = stencil_pcg(f, b, tol, maxit)
2+
% STENCIL_PCG computes CG with 1st order approximation for f
3+
4+
its = 0;
5+
flg = 1;
6+
7+
e = 1e-08;
8+
9+
x0 = zeros(size(b)); % initial guess
10+
x = x0;
11+
12+
13+
Fx = f(x);
14+
xx = (1+e)*x;
15+
Fxx = f(xx);
16+
r = b - (1/e) * (Fxx - Fx); % A*x \approx (1/e) * (Fxx-Fx)
17+
p = r;
18+
19+
resOld = r'*r;
20+
resNew = resOld;
21+
22+
if (sqrt(resOld) < tol)
23+
flg = 0;
24+
%fprintf('STENCIL_CG: converged in 0 iterations (initial guess is good enough!\n');
25+
return;
26+
end
27+
28+
for its = 1:maxit
29+
30+
%fprintf('STENCIL_CG: %3d ', its);
31+
32+
Fx = f(x);
33+
xx = x + e*p;
34+
Fxx = f(xx);
35+
Ap = (1/e) * (Fxx-Fx); % A*p approx. by Ap
36+
%fprintf(' * RES. FOR Ap = %.4e * ', norm(Ap-A*p)/norm(A*p));
37+
38+
alpha = r'*r / (p'*Ap);
39+
40+
x = x + alpha * p;
41+
rnew = r - alpha * Ap;
42+
43+
resNew = rnew' * rnew;
44+
if (sqrt(resNew) < tol)
45+
flg = 0;
46+
break;
47+
end
48+
49+
beta = resNew / resOld; % res=<r(k-1),r(k-1)>, resNew=<r(k+1),r(k+1)>
50+
p = rnew + beta * p;
51+
52+
r = rnew;
53+
resOld = resNew;
54+
%fprintf(' - RELRES: %.4e\n', sqrt(resNew));
55+
56+
end
57+
58+
if flg == 0
59+
%fprintf('STENCIL_CG: converged in %d iterations.\n', its);
60+
else
61+
%fprintf('STENCIL_CG: could NOT converge.\n');
62+
end
63+
64+
end
65+
66+
67+

0 commit comments

Comments
 (0)