sandbox/easystab/stab2014/Roughness.m
UNFINISHED Roughness simulation page
Coded by Paul Valcke and Luis Bernardos. This code has not been finished, it is an attempt to calculate the roughness effect in a multi-domain mesh. The code programmatically creates several meshes and imposes the link conditions between all domains also programmatically. Through the parameter N_{cav} The user can specify as many cavities as desired, and the code will mesh and construct the C matrix programmatically.
We did not have enough time for accomplishing this interesting job, and we hope future contributors will like the idea and continue working in this direction.
clear all; figure('OuterPosition',[100, 100, 800, 400]); format compact
%%%% parameters
Re=1000; % reynolds number
Lin = 1; % Length before roughness
DiamInlet = 1; % Diameter of main tube
Lcav = 0.2; % Length of roughness
Dcav = 0.2; % Depth of roughness
Ncavs = 10; % Number of cavities defining roughness
Ny_main = 30; % Number of vertical divisions of main tube
Nx_inlet = 10; % Number of horizontal divisons of inlet
Ny_cav = 10; % Number of vertical divisons of cavity
Nx_cav = 10; % Number of horizontal divisons of cavity.
% Speed of inlet
Uinlet = Re*1.79e-5/(1.225*DiamInlet);
pts=5; % number of points in finite difference stencils
alpha=1; % Under-relaxation
maxIter = 200;
resSTOP = 1e-5;
dt = 0.1;
tmax = 6;
% differentiation
D = cell(3*Ncavs+1,1); l=D;X=D;Y=D;Z=D;I=D; NN = zeros(3*Ncavs+1,1);% Pre-allocation
[d.x,d.xx,d.wx,x]=dif1D('fd',0,Lin,Nx_inlet,pts);
[d.y,d.yy,d.wy,y]=dif1D('fd',0,DiamInlet,Ny_main,pts);
[D{1},l{1},X{1},Y{1},Z{1},~,NN(1)]=dif2D(d,x,y);
G = 0;
for i = 1:3:3*Ncavs
G = G+1;
[d.x,d.xx,d.wx,x]=dif1D('fd',Lin+(G-1)*2*Lcav,Lcav,Nx_cav,pts);
[d.y,d.yy,d.wy,y]=dif1D('fd',0,DiamInlet,Ny_main,pts);
[D{i+1},l{i+1},X{i+1},Y{i+1},Z{i+1},~,NN(i+1)]=dif2D(d,x,y);
[d.x,d.xx,d.wx,x]=dif1D('fd',Lin+(G-1)*2*Lcav,Lcav,Nx_cav,pts);
[d.y,d.yy,d.wy,y]=dif1D('fd',0,-Dcav,Ny_cav,pts);
[D{i+2},l{i+2},X{i+2},Y{i+2},Z{i+2},~,NN(i+2)]=dif2D(d,x,y);
[d.x,d.xx,d.wx,x]=dif1D('fd',Lin+(G-1)*2*Lcav+Lcav,Lcav,Nx_cav,pts);
[d.y,d.yy,d.wy,y]=dif1D('fd',0,DiamInlet,Ny_main,pts);
[D{i+3},l{i+3},X{i+3},Y{i+3},Z{i+3},~,NN(i+3)]=dif2D(d,x,y);
end
Dx=D{1}.x;
Dy=D{1}.y;
Dxx=D{1}.xx;
Dyy=D{1}.yy;
ZZ=Z{1};
for i = 2:3*Ncavs+1
Dx=blkdiag(Dx,D{i}.x);
Dy=blkdiag(Dy,D{i}.y);
Dxx=blkdiag(Dxx,D{i}.xx);
Dyy=blkdiag(Dyy,D{i}.yy);
ZZ=blkdiag(ZZ,Z{i});
end
Dlap=Dyy+Dxx;
NNsum=sum(NN);
% Plot mesh
for i = 1:3*Ncavs+1
mesh(X{i},Y{i},0*X{i},'edgecolor','k'); view(2); grid off;hold on
end
xlabel('X');ylabel('Y'),title('Mesh of the roughness');hold off;axis equal;
drawnow
set(gcf,'paperpositionmode','auto')
print('-dpng','-r90','RoughnessMesh.png');
break
Boundary conditions
%%%% preparing boundary conditions
u = cell(3*Ncavs+1,1); v=u; p=u; % pre-allocates
u{1}=(1:NN(1))';
for i = 2:3*Ncavs+1
u{i}=u{i-1}+NN(i);
end
v{1}=u{end}+NN(1);
for i = 2:3*Ncavs+1
v{i}=v{i-1}+NN(i);
end
p{1}=v{end}+NN(1);
for i = 2:3*Ncavs+1
p{i}=p{i-1}+NN(i);
end
II=speye(3*NNsum);
% Dirichlet Conditions
dir = cell(3*Ncavs+1,1);lnkMM=dir;lnkM=dir;lnkP=dir;lnkPP=dir;loc=dir; % Preallocates
dir{1}=[l{1}.ctl;l{1}.left;l{1}.cbl;l{1}.top;l{1}.bot;l{1}.ctr;l{1}.cbr]; % where to put Dirichlet on u1 and v1
lnkMM{1}=[]; % Link with previous of the previous domain
lnkM{1}=[]; % Link with previous domain
lnkP{1}= l{1}.right; % Link with next domain
lnkPP{1}=[]; % Link with next to the next domain
loc{1}=[u{1}(dir{1}); v{1}(dir{1}); % Dirichlet
u{1}(lnkP{1}); v{1}(lnkP{1}); p{1}(lnkP{1})]; % Link
G = 0;
for i = 2:3:3*Ncavs+1
G = G+1;
dir{i}=[l{i}.ctl;l{i}.top;l{i}.cbl;l{i}.cbr]; % where to put Dirichlet on u v
lnkMM{i}=[];
lnkM{i}=l{i}.left; % Link with previous domain
lnkP{i}=l{i}.bot; % Link with next domain
lnkPP{i}=l{i}.right; % Link with next to the next domain
loc{i}=[u{i}(dir{i}); v{i}(dir{i}); % Dirichlet
u{i}(lnkM{i}); v{i}(lnkM{i}); p{i}(lnkM{i});
u{i}(lnkP{i}); v{i}(lnkP{i}); p{i}(lnkP{i});
u{i}(lnkPP{i}); v{i}(lnkPP{i}); p{i}(lnkPP{i})]; % Link
dir{i+1}=[l{i+1}.ctl;l{i+1}.left;l{i+1}.cbl;l{i+1}.bot;l{i+1}.cbr;l{i+1}.right;l{i+1}.ctr]; % where to put Dirichlet on u v
lnkMM{i+1}=[];
lnkM{i+1}=l{i+1}.top; % Link
lnkP{i+1}=[]; % Link with next domain
lnkPP{i+1}=[]; % Link with next to the next domain
loc{i+1}=[u{i+1}(dir{i+1}); v{i+1}(dir{i+1}); % Dirichlet
u{i+1}(lnkM{i+1}); v{i+1}(lnkM{i+1}); p{i+1}(lnkM{i+1})]; % Link
dir{i+2}=[l{i+2}.ctl;l{i+2}.cbl;l{i+2}.bot;l{i+2}.cbr;l{i+2}.ctr]; % where to put Dirichlet on u v
lnkMM{i+2}=l{i+2}.left;
lnkM{i+2}=[]; % Link
lnkP{i+2}=[];
lnkPP{i+2}=[];
loc{i+2}=[u{i+2}(dir{i+2}); v{i+2}(dir{i+2}); % Dirichlet
u{i+2}(lnkMM{i+2}); v{i+2}(lnkMM{i+2}); p{i+2}(lnkMM{i+2})]; % Link
if G == Ncavs
neu=l{i+2}.right;
loc{i+2}=[loc{i+2}; u{i+2}(neu); v{i+2}(neu)];
else
lnkP{i+2}=l{i+2}.right;
loc{i+2}=[loc{i+2};u{i+2}(lnkP{i+2}); v{i+2}(lnkP{i+2}); p{i+2}(lnkP{i+2})];
end
end
loc = cell2mat(loc(:));
% =================================
% CONSTRUCTION OF CONSTRAINT MATRIX
% =================================
C = II(u{1}(dir{1}),:);
% Dirichlet conditions:
for i = 2:3*Ncavs+1
C = [C;II([u{i}(dir{i});v{i}(dir{i})],:)];
end
% Link Continuity
for i = 1:3*Ncavs
C=[C;II([u{i}(lnkP{i});v{i}(lnkP{i});p{i}(lnkP{i})],:)-II([u{i+1}(lnkM{i+1});v{i+1}(lnkM{i+1});p{i+1}(lnkM{i+1})],:);
% Link Tangency
% on u
[Dx(lnkP{i}+sum(NN(1:i-1)),:)-Dx(lnkM{i+1}+sum(NN(1:i)),:),ZZ(lnkP{i}+sum(NN(1:i-1)),:),ZZ(lnkP{i}+sum(NN(1:i-1)),:)];
% on v
[ZZ(lnkP{i}+sum(NN(1:i-1)),:),Dx(lnkP{i}+sum(NN(1:i-1)),:)-Dx(lnkM{i+1}+sum(NN(1:i)),:),ZZ(lnkP{i}+sum(NN(1:i-1)),:)];
% on p
[ZZ(lnkP{i}+sum(NN(1:i-1)),:),ZZ(lnkP{i}+sum(NN(1:i-1)),:),Dx(lnkP{i}+sum(NN(1:i-1)),:)-Dx(lnkM{i+1}+sum(NN(1:i)),:)]];
if i<3*Ncavs
C=[C;II([u{i}(lnkPP{i});v{i}(lnkPP{i});p{i}(lnkPP{i})],:)-II([u{i+2}(lnkMM{i+2});v{i+2}(lnkMM{i+2});p{i+2}(lnkMM{i+2})],:);
[Dx(lnkPP{i}+sum(NN(1:i-1)),:)-Dx(lnkMM{i+2}+sum(NN(1:i)),:),ZZ(lnkPP{i}+sum(NN(1:i-1)),:),ZZ(lnkPP{i}+sum(NN(1:i-1)),:)];
[ZZ(lnkPP{i}+sum(NN(1:i-1)),:),Dx(lnkPP{i}+sum(NN(1:i-1)),:)-Dx(lnkMM{i+2}+sum(NN(1:i)),:),ZZ(lnkPP{i}+sum(NN(1:i-1)),:)];
[ZZ(lnkPP{i}+sum(NN(1:i-1)),:),ZZ(lnkPP{i}+sum(NN(1:i-1)),:),Dx(lnkPP{i}+sum(NN(1:i-1)),:)-Dx(lnkMM{i+2}+sum(NN(1:i)),:)]];
end
end
% Neumann
C=[C;[Dx(neu+sum(NN(1:3*Ncavs)),:), ZZ(neu+sum(NN(1:3*Ncavs)),:), ZZ(neu+sum(NN(1:3*Ncavs)),:)];
[ZZ(neu+sum(NN(1:3*Ncavs)),:), Dx(neu+sum(NN(1:3*Ncavs)),:), ZZ(neu+sum(NN(1:3*Ncavs)),:)]];
break
% CUALQUIER PARECIDO CON LA REALIDAD ES PURA COINCIDENCIA...
% C=[II([u1(dir1);v1(dir1);u2(dir2);v2(dir2)],:);% Dirichlet on u,v
% II([u1(lnk1);v1(lnk1);p1(lnk1)],:)-II([u2(lnk2);v2(lnk2);p2(lnk2)],:); % Link Continuity
% D.x(lnk1,:)-D.x(lnk2+NN1,:), Z(lnk1,:), Z(lnk1,:); % Link Tangency on u
% Z(lnk1,:),D.x(lnk1,:)-D.x(lnk2+NN1,:), Z(lnk1,:); % Link Tangency on v
% Z(lnk1,:), Z(lnk1,:),D.x(lnk1,:)-D.x(lnk2+NN1,:); % Link Tangency on p
% D.x(neu+NN1,:), Z(neu+NN1,:), Z(neu+NN1,:); % Neumann on u2 at outflow
% Z(neu+NN1,:), D.x(neu+NN1,:), Z(neu+NN1,:)]; % Neumann on v2 at outflow
We chose an initial guess that statisfies the boundary conditions, this is good for Newton, and it makes it also very easy to impose the nonhomogeneous boundary conditions in the lop.
% initial guess
U1 = zeros(NN1,1);
U1(l1.left) = Uinlet;%1.5.*Uinlet.*(1-((2.*(y_inlet-min(y_inlet)))./DiamInlet - 1).^2);
V1=zeros(NN1,1);
P1=ones(NN1,1);
U2 = zeros(NN2,1);
V2=zeros(NN2,1);
P2=ones(NN2,1);
U = [U1;U2];
V = [V1;V2];
P = [P1;P2];
sol0=[U1(:);U2(:);V1(:);V2(:);P1(:);P2(:)];
% Newton iterations
disp('Newton loop')
sol=sol0;
solNm1 = sol0;
solM=sol;
quit=0;count=0;time = 0;
for t = 0:dt:tmax
while ~quit
% the present solution and its derivatives
UM = solNm1([u1;u2]); % Solution du pas précédant
VM = solNm1([v1;v2]);
PM = solNm1([p1;p2]);
U=alpha.*sol([u1;u2]) + (1-alpha).*solM([u1;u2]);
V=alpha.*sol([v1;v2]) + (1-alpha).*solM([v1;v2]);
P=alpha.*sol([p1;p2]) + (1-alpha).*solM([p1;p2]);
Ux=D.x*U; Uy=D.y*U;
Vx=D.x*V; Vy=D.y*V;
Px=D.x*P; Py=D.y*P;
This is now the heart of the code: the expression of the nonlinear fonction that should become zero, and just after, the expression of its Jacobian, then the boundary conditions.
% nonlinear function
f=[UM-U-(U.*Ux+V.*Uy+Px-(D.lap*U)/Re).*dt; ...
VM-V-(U.*Vx+V.*Vy+Py-(D.lap*V)/Re).*dt; ...
D.x*U+D.y*V];
% Jacobian
A=[-spd(ones(NN,1))+dt.*(-(spd(Ux)+spd(U)*D.x + spd(V)*D.y )+(D.lap)/Re), -spd(Uy).*dt, (-D.x).*dt; ...
-spd(Vx).*dt, -spd(ones(NN,1))+dt.*(-(spd(Vy) + spd(V)*D.y + spd(U)*D.x )+(D.lap)/Re), (-D.y).*dt; ...
D.x, D.y, Z];
% Boundary conditions
f(loc)=C*(sol-sol0);
A(loc,:)=C;
% convergence test
res=norm(f);
disp([num2str(count) ' ' num2str(res)]);
if (count>maxIter) || (res>1e5); disp('no convergence');break; end
if res<resSTOP; quit=1; disp('converged'); end
% Newton step
solM = sol;
sol=solM-A\f;%gmres(A,f,1000,1e-7);%A\f;
count=count+1;
% % NewtonPlot
% Module = sqrt((U.^2+V.^2));
% surf([X1,X2],[Y1,Y2],reshape(Module,Ny,2*Nx)); view(2); shading interp; hold on
% xlabel('x'); ylabel('y');grid off;hold off
% colorbar;
% axis equal
% drawnow
end
count = 0;
solNm1 = sol;
quit = 0;
time =time+dt;
fprintf('t=%g\n',time);
% plotting
Module = sqrt((U.^2+V.^2));
surf([X1,X2],[Y1,Y2],reshape(Module,Ny,2*Nx)); view(2); shading interp; hold on
caxis([0 2*Uinlet]); % Color scale
xlabel('x'); ylabel('y'); title(sprintf('Poiseuille t=%0.1fs ; Uinlet = %0.3fm/s; Reynolds %d',time,Uinlet,Re)); grid off;hold off
colorbar;
axis equal
drawnow
set(gcf,'paperpositionmode','auto')
print('-dpng','-r80',sprintf('Poiseuille_t%0.1fs.png',time));
end
% Creates animated gif
FirstFrame = true;
gifname = sprintf('Poiseuille_Re%d.gif',Re);
for t = 3*dt:dt:tmax
im = imread(sprintf('Poiseuille_t%0.1fs.png',t));
[imind,cm] = rgb2ind(im,256);
if FirstFrame
imwrite(imind,cm,gifname,'gif','Loopcount',inf);
FirstFrame = false;
else
imwrite(imind,cm,gifname,'gif','WriteMode','append',...
'DelayTime',dt);
end
end