% This program solves a 2D transient convection-diffusion-reaction equation
% in a domain [0,2]x[0,3]
% with Dirichlet boundary conditions
% using the finite element method

clear; close all; clc;

disp(' ')
disp('This program solves a 2D unsteady convection-diffusion-reaction equation in [0,2]x[0,3]')
dom = [0,2,0,3];

%% Element type
% elem: 0=quadrilateral, 1=triangles
% p: 1=linear, 2=quadratic
disp(' ')
elem = cinput('Element shape: 0=quadrilateral, 1=triangles',0);
p = cinput('Element type: 1=linear, 2=quadratic',1);
referenceElement = SetReferenceElement(elem,p); 

disp(' ')
nx = cinput('Number of elements in x-direction',20);
ny = cinput('Number of elements in y-direction',30);
[X,T] = CreateMesh(dom,nx,ny,referenceElement);
figure; PlotMesh(T,X,'b-');

%% PDE coefficients
% velocity field
disp(' ')
disp('The following velocity fields can be considered');
disp('   [1] v(x,y) = (0.001,0)');
disp('   [2] v(x,y) = (-1,0)');
disp('   [3] v(x,y) = (-0.001,0)'); 
disp('   [4] v(x,y) = (cos(pi/6),sin(pi/6))'); 
disp('   [5] v(x,y) = (1,0)');
c_velo = cinput('Choose the convection field to be used on the computation',1); 

switch c_velo
    case 1
        velo = [0.001,0];
        a = norm(velo);
    case 2
        velo = [-1,0];
        a = norm(velo);
    case 3
        velo = [-0.001,0];
        a = norm(velo);
    case 4
        velo = [cos(pi/6),sin(pi/6)];
        a = norm(velo);
    case 5
        velo = [1,0];
        a = norm(velo);
end

% diffusion coefficient
disp(' ')
nu = cinput('Diffusion coefficient', 0.001);

% reaction coefficient
disp(' ')
disp('The following reaction coefficient can be considered');
disp('   [1] sigma = 1');
disp('   [2] sigma = 0.001');
disp('   [3] sigma = 0');
c_sigma = cinput('Choose the reaction coefficient to be used on the computation',1);

switch c_sigma
    case 1
        sigma = 1;
    case 2
        sigma = 0.001;
    case 3
        sigma = 0;
end

% source term
disp(' ')
disp('The following source term can be considered');
disp('   [1] s = 0');
disp('   [2] s = 1');
c_source = cinput('Choose the source term to be used on the computation',1);

switch c_source
    case 1
        source = 0;
    case 2
        source = 1;
end

example.dom = dom;
example.velo = velo;
example.a = a;
example.nu = nu;
example.sigma = sigma;
example.source = source;

%% Time discretization
disp(' ')
tEnd = cinput('End time', 2);
nStep = cinput('Numnber of time-steps', 100);
dt = tEnd / nStep; 

%% Peclet
h = (dom(2)-dom(1))/nx;
Pe = a*h/(2*nu);
disp(' ')
disp(strcat('Peclet number: ',num2str(Pe)))

%tau_p = 1/(2/dt+2*a/h+4*nu/h^2+sigma); %for theta-method
tau_p = h*(1 + 9/Pe^2)^(-1/2)/(2*a);
%tau_p = (h/2*a)*(coth(Pe)-1/Pe)*2;
disp(strcat('Recommended stabilization parameter = ',num2str(tau_p)));
tau = cinput('Stabilization parameter',tau_p);
if isempty(tau)
    tau = tau_p;
end

Courant = a*dt/h; 
disp(strcat('Courant number: ', num2str(Courant)))

%% Boundary conditions
% Boundary conditions are imposed using Lagrange multipliers
nodes_x0 = [ny*(nx+1)+1:-(nx+1):1]';     % Nodes on the boundary x=0
nodes_x2 = [(nx+1):nx+1:(ny+1)*(nx+1)]' ;     % Nodes on the boundary x=2

% nodes on which solution is u=1
nodesDir1 = nodes_x0( X(nodes_x0,2) > 1.5 );
% nodes on which solution is u=0
nodesDir0 = nodes_x2;
% Boundary condition matrix
BC = [nodesDir1, ones(length(nodesDir1),1);
     nodesDir0, zeros(length(nodesDir0),1)];
 
%% Initial condition
u0 = InitialCondition(X,nodesDir1,nodesDir0); 

xx  = reshape(X(:,1), nx+1, ny+1)'; 
yy  = reshape(X(:,2), nx+1, ny+1)'; 
u0_dib = reshape(u0, nx+1, ny+1)';  
figure(2); clf; 
surface(xx,yy,u0_dib,'FaceColor','interp');
set(gca, 'xTick',0:0.5:2, 'yTick',0:0.5:3, 'FontSize',12)
xlabel('x','FontSize',14); 
ylabel('y','FontSize',14); 
zlabel('u','FontSize',14);
grid on
view(3)
figure(3); clf;
[C,h]=contour(xx,yy,u0_dib,[-0.1,-0.01,0.1:0.1:1.0]);
clabel(C,h,'FontSize',12);
axis equal; axis(dom);
set(gca,'FontSize',16,'XTick',0:0.25:2,'YTick',0:0.25:3)

%% method
disp(' ')
disp ('The following methods can be used:');
disp ('     [0] Galerkin+CN(R11)');
disp ('     [1] SUPG+CN(R11)');
disp ('     [2] GLS+CN(R11)');
disp ('     [3] SUPG+LAX(R20)');
disp ('     [4] GLS+LAX(R20)');
method = input ('Choose a method for solving the problem: ');
example.method = method; 

%% System resulting of discretizing the weak form
[M,K,K1,C,C1] = FEM_matrices(X,T,velo,referenceElement);
[A,B,methodName] = System(method,M,K,K1,C,C1,a,dt,tau,nu,sigma); 

nPt = size(X,1);
f = zeros(nPt,1);

%% Solution at each time step
u = zeros(nPt,nStep+1);
u(:,1) = u0;
u(nodesDir1,:)=1;
u(nodesDir0,:)=0;
du=zeros(nPt,1);
if method<3 % 1 stage
    for n=1:nStep
        rhs = B*u(:,n)+f+A*u(:,n);
        BC = [nodesDir1, ones(length(nodesDir1),1);
              nodesDir0, zeros(length(nodesDir0),1)];
        nDir = size(BC,1);
        neq = size(f,1);
        LM = zeros(nDir,neq);
        LM(:,BC(:,1)) = eye(nDir);
        b = BC(:,2);
        Ktot = [A LM';LM zeros(nDir,nDir)];
        ftot = [rhs;b];
        sol = Ktot\ftot;
        u(:,n+1) = sol(1:neq);
        
    end
else % 2 stage
    for n = 1:nStep
        % stage 1
        rhs = B*u(:,n)+f+A*u(:,n);
        BC = [nodesDir1, ones(length(nodesDir1),1);
              nodesDir0, zeros(length(nodesDir0),1)];
        nDir = size(BC,1);
        neq = size(f,1);
        LM = zeros(nDir,neq);
        LM(:,BC(:,1)) = eye(nDir);
        b = BC(:,2);
        Ktot = [A LM';LM zeros(nDir,nDir)];
        ftot = [rhs;b];
        sol = Ktot\ftot;
        temp = sol(1:neq); %u(n+1/2)
        
        % stage 2
        rhs = 2*B*u(:,n)+f+A*temp;
        ftot = [rhs;b];
        sol = Ktot\ftot;
        u(:,n+1)=sol(1:neq);
    end
end


%% plots
figure(4), clf
xx  = reshape(X(:,1), nx+1, ny+1)'; 
yy  = reshape(X(:,2), nx+1, ny+1)'; 
sol = reshape(u(:,end), nx+1, ny+1)';  
surface(xx,yy,sol,'FaceColor','interp');
set(gca, 'xTick',0:0.25:2, 'yTick',0:0.25:3, 'FontSize',12)
xlabel('x','FontSize',14); 
ylabel('y','FontSize',14); 
zlabel('u','FontSize',14);
grid on; view(3)

%figure(5), clf
i=5;
for n = 1:nStep+1
    figure(i), clf
    tt = (n-1)*dt;
    sol = reshape(u(:,n), nx+1, ny+1)';  
    surface(xx,yy,sol,'FaceColor','interp');
    set(gca, 'xTick',0:0.25:2, 'yTick',0:0.25:3, 'FontSize',12)
    xlabel('x','FontSize',14); 
    ylabel('y','FontSize',14); 
    zlabel('u','FontSize',14);
    grid on; view(3)
    title(['t=',num2str(tt)])
    i=i+1;
    %pause(0.05)
end
%save('GLS_test')
%save('SUPG_test')