% This program solves the leaky cavity-flow Navier-Stokes problem
% using a mixed finite element formulation.
%


clear all, close all, home

global nu;


disp(' ')
disp('CAVITY FLOW NAVIER-STOKES PROBLEM')

disp(' ')
Re = input('Reynolds number = ');
nu = 3/Re;

% MIXED ELEMENT USED FOR THE SOLUTION
disp(' ')
disp('The problem is solved using a mixed fomulation.')
disp('The following elements are available: ')
disp('Quadrilaterals')
disp('         [0]: Q1P0    [1]: Q1Q1    [2]: Q2Q1   [3]: Q2Q2')
disp('Triangles')
disp('         [4]: P1P0    [5]: P1P1    [6]: P1+P1 (MINI)    [7]: P2P1   [8]: P2P2')
imix = input('Choose the element for the solution :  ');
% Type of element (0 for quadrilaterals and 1 for triangles)
% and number of element nodes for velocity (nen) and pressure (nenP).
if imix == 0
    elem = 0;
    nen = 4; nenP = 1;
elseif imix == 1
    elem = 0;
    nen = 4; nenP = 4;
elseif imix == 2
    elem = 0;
    nen = 9; nenP = 4;
elseif imix == 3
    elem = 0;
    nen = 9; nenP = 9;
elseif imix == 4
    elem = 1;
    nen = 3; nenP = 1;
elseif imix == 5
    elem = 1;
    nen = 3; nenP = 3;
elseif imix == 6
    elem = 1;
    nen = 4; nenP = 3;
elseif imix == 7
    elem = 1;
    nen = 6; nenP = 3;
elseif imix == 8
    elem = 1;
    nen = 6; nenP = 6;
else
    error('Unavailable element')
end

% GEOMETRY
% Number of nodes on each direction
disp(' ')
npx = input('Number of nodes in X direction (default: 21)= ');
npy = input('Number of nodes in Y direction (default: npx)= ');
if isempty(npx)  npx = 21;     end
if isempty(npy)  npy = npx;    end
% Number of elements on each direction
nx = npx-1; ny = npy-1;
npt = npx*npy;

% Coordinates of domain's vertices
x_lo = 0; x_up = 2; 
y_lo = 0; y_up = 3; 
% Nodal coordinates matrix and connectivities for velocity 
disp('Problem is solved on an structured mesh.')
disp('It can be uniform ([1]) or adapted to the problem ([2]).')
meshtype = input('Choose a computational mesh (default: uniform): ');
if isempty(meshtype)
    meshtype = 1;
end
if meshtype == 1
    [X,T] = CreateUniformMesh(elem,nen,x_lo,x_up,y_lo,y_up,npx,npy);      
elseif meshtype == 2
    [X,T] = CreateMesh(elem,nen,x_lo,x_up,y_lo,y_up,npx,npy);    
else
    error('Unavailable mesh option')
end
% Nodal coordinates matrix and connectivities for pressure
[XP,TP] = CreatePresNod(elem,nenP,X,T,npx,npy);

% Total number of nodes and degrees of freedom
if elem == 1 & nen == 4     % MINI
    numnp = size(X,1) + size(T,1);
    nunk = 2*numnp;
else
    numnp = size(X,1); 
    nunk = 2*numnp;
end
ndofP = size(XP,1);

% Meshes plots
figure('Name','Mesh for velocity','NumberTitle','off'); clf;
PlotMesh(T,X,elem,'b')
%title('Computational mesh for the velocity field')
figure('Name','Mesh for pressure','NumberTitle','off'); clf;
PlotMesh(TP,XP,elem,'r')
%title('Computational mesh for the velocity field')
figure('Name','Meshes','NumberTitle','off'); clf;
PlotMesh(T,X,elem,'b'),     hold on
PlotMesh(TP,XP,elem,'r'),   hold off

% BOUNDARY CONDITIONS
[Accd, bccd,velo_ini] = BC_Cavity(nx,ny,nunk,X);
% confined flow (only essential conditions on the velocity are imposed)
confined = 1;     
% number of prescribed degrees of freedom
nDir = size(Accd,1);


% SOLUTION
% Computation of matrices
[K,G,f] = CreMat(X,T,XP,TP,elem);
if confined
   nunkP = ndofP-1;
   disp(' ')
   disp('Confined flow. Pressure on lower left corner is set to sero');
   G(1,:)=[];
else
   nunkP = ndofP;
end

% Entire r.h.s. vector (including boundary conditions)
btot = [f ; bccd ; zeros(nunkP,1)];

% Vectors used to carry out the nonlinear computation
aux =  zeros(length(btot),1);
velo = zeros(numnp,2);
mlag = zeros(nDir,1)   ; 
pres = zeros(ndofP,1)  ;

% Initial velocity field
% If there is no initial velocity available, we use a field which is 
% zero everywhere but on the boundary, where Dirichlet conditions are imposed
inivelfile = input('Initial velocity file (RETURN: No) = ','s');
if isempty(inivelfile)
    velo = velo_ini;
else
   disp(inivelfile); load(inivelfile);
end
clear velo_ini; pack;
aux  = [reshape(velo',nunk,1);mlag;pres(1:nunkP)];
% Initial velociy plot
figure('Name','Initial velocity','NumberTitle','off'); clf;
quiver(X(1:npt,1),X(1:npt,2),velo(1:npt,1),velo(1:npt,2),2);
box on; axis equal;
set(gca, 'FontSize', 12,...
    'XTick', [0:0.25:2], 'YTick', [0:0.25:3]);
axis([0,2,0,3])
pause(1)
iter = 0; tol =0.5e-5;
disp(' ')
while iter<100
    fprintf('Iteration = %d\n',iter);
    % Computation of the convection matrix
    Cv = CreConv(velo,X,T,elem);
    % Entire matrix, including boundary conditions
    Atot = [K+Cv Accd' G'; ...
           Accd zeros(nDir,nDir)  zeros(nDir,nunkP); ...
           G    zeros(nunkP,nDir) zeros(nunkP,nunkP)];
    % Computation of residual
    bnew = btot - Atot*aux;
    % Computation of velocity and pressure increment
    aux = Atot\(bnew);
    velo = velo + reshape(aux(1:nunk),2,numnp)';
    mlag = mlag + aux(nunk+1:nunk+nDir);
    if confined
        pres = pres + [0;aux(nunk+nDir+1:nunk+nDir+nunkP)];
    else
        pres = pres + aux(nunk+nDir+1:nunk+nDir+nunkP);
    end
    delta1 = max(abs(aux(1:nunk)));
    delta2 = max(abs(bnew));
    fprintf('Velocity increment=%8.6e, Residue max=%8.6e\n',delta1,delta2)
    if (delta1<tol*max(abs(reshape(velo,1,nunk)))) & (delta2< tol)
        disp(' ')
        fprintf('Convergence achieved in iteration number: %d\n',iter)
        break;
    end
    aux  = [reshape(velo',nunk,1);mlag;pres(2:nunkP+1)];
    iter = iter + 1;
    % Solution at current iteration
    % These lines are commented for faster computation
    % phi = StreamLines_ls(X,T,elem,velo,npx,npy,[],5);
    % hold on
    % quiver(X(1:npt,1),X(1:npt,2),velo(1:npt,1),velo(1:npt,2),'r');
    % box on; axis equal tight; 
    % pause(0.1)
    % figure(6); clf;
    % tri=delaunay(XP(:,1),XP(:,2));
    % trisurf(tri,XP(:,1),XP(:,2),pres);        
    % pause(0.1)
    % if iter == 1
    %     h = msgbox('Arrange windows in order to see reults properly');
    %     uiwait(h)
    % end
end

clear aux;

% POSTPROCESS
% Velocity 
figure('Name','Velocity field','NumberTitle','off'); clf;
quiver(X(1:npt,1),X(1:npt,2),velo(1:npt,1),velo(1:npt,2),2);
box on; axis equal;
set(gca, 'FontSize', 12,...
    'XTick', [0:0.25:2], 'YTick', [0:0.25:3]);
axis([0,2,0,3])

% Pressure 
if elem == 0
    if (imix == 0)
        x = []; y = []; z = [];
        for e = 1:nx*ny
            x = [x, X(T(e,:),1)];
            y = [y, X(T(e,:),2)];
            z = [z, pres(e)*ones(4,1)];
        end
        figure('Name','Pressure field','NumberTitle','off'); clf;
        patch(x,y,z,z)
        view(3); grid on;
        set(gca, 'FontSize', 12,...
            'XTick', [0:0.25:2], 'YTick', [0:0.25:3]);
    elseif (imix == 1 | imix == 3)
        aux_x = ones(npy,1)*X(1:npx,1)';
        aux_y = X(1:npx:npt,2)*ones(1,npx);
        aux_p = reshape(pres,npx,npy)';
        figure('Name','Pressure field','NumberTitle','off'); clf;
        surface(aux_x, aux_y, aux_p,'FaceColor','interp')       
        view(3); grid on;
        set(gca, 'FontSize', 12,...
            'XTick', [0:0.25:2], 'YTick', [0:0.25:3]);        
    elseif (imix == 2)
        aux_x = ones(ny/2+1,1)*X(1:2:npx,1)';
        aux_y = X(1:2*npx:npt,2)*ones(1,nx/2+1);
        aux_p = reshape(pres, nx/2+1, ny/2+1)';
        figure('Name','Pressure field','NumberTitle','off'); clf;
        surface(aux_x, aux_y, aux_p,'FaceColor','interp')
        view(3); grid on;
        set(gca, 'FontSize', 12,...
            'XTick', [0:0.25:2], 'YTick', [0:0.25:3]);
    end
else
    figure('Name','Pressure field','NumberTitle','off'); clf;
    tri = delaunay(XP(:,1),XP(:,2));
    trisurf(tri,XP(:,1),XP(:,2),pres);
    view(3); grid on;
    set(gca, 'FontSize', 12,...
        'XTick', [0:0.25:2], 'YTick', [0:0.25:3]);
end
% Streamlines (computed as level sets)
phi = StreamLines_ls(X,T,elem,velo,npx,npy);

% Streamlines (using Matlab function)
sx = [0:0.1:1, 0.5*ones(1,11), 0:0.1:1, 1:-0.1:0];
sy = [0.5*ones(1,11), 0:0.1:1, 0:0.1:1, 0:0.1:1];
StreamLines(X,velo,npx,npy,sx,sy), hold on
plot([x_lo,x_up,x_up,x_lo,x_lo],[y_lo,y_lo,y_up,y_up,y_lo],'k','LineWidth',2)
axis equal; axis([0,2,0,3]); box on;
hold off
