% This program solves a convection-diffusion-reaction problem 
% in a square domain [0,2]x[0,3]

clear; close all; clc   


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

dom = [0,2,0,3]; 

% Element type
disp(' ')
elem = 0; p = 1; %p=1 linear elements, p=2 quadratic elements
referenceElement = SetReferenceElement(elem,p); 

nx = cinput('Number of elements in each direction',10);
ny = cinput('Number of elements in each direction',15);
[X,T] = CreateMesh(dom,nx,ny,referenceElement);
nNodes = length(X);
h = dom(2)/nx;
PlotMesh(T,X,'b-');

disp(' ')
disp('The following velocity fields can be considered');
disp('   [1] v(x,y) = (-x,-y)');
disp('   [2] v(x,y) = (1,0)');
disp('   [3] v(x,y) = (1,1)/sqrt(2)'); 
velo = cinput('Choose the convection field to be used on the computation',1);
Conv = ComputeVelocity(X,velo);
a=max(sqrt(Conv(:,1).^2 + Conv(:,2).^2));

nu = cinput('Diffusion coefficient',1);
sigma = cinput('Reaction coefficient',1);

Pe = a*h/(2*nu);

% Time discretization
Courant = 1;
dt = (Courant*h)/a;
nStep = cinput('Number of time-steps', 110);
tEnd = nStep*dt;

% Solvers
% Method used for solving the problem
disp(' ')
disp ('The problem can be solved using one of the following methods: ');
disp ('    [1] Crank-Nicolson + Galerkin')
disp ('    [2] R22 + Galerkin')
disp ('    [3] Crank-Nicolson + SUPG')
disp ('    [4] R22 + SUPG')
method = input('Method = ');


tic

[M,Ka,C,K,Dif] = FEM_matrices(X,T,Conv,referenceElement); 
%[Mout,Cout] = Boundary_matrices(X,T,Conv,referenceElement,velo);

% Boundary conditions (Lagrange multipliers)
[ADir,bDir,nDir,nodesDir1,nodesDir0] = BoundaryConditions(X,velo, nx, ny);
zDir= zeros(nDir);

% Initial Condition
u0 = InitialCondition(X,nodesDir1,nodesDir0);

% Initializing the variable matrix
u = zeros(nNodes,nStep);
u(:,1) = u0;

W = 0;
w = 0;
tau = 0;
if method == 2
    W = (1/24)*[7 -1; 13 5];
    w = [1/2; 1/2];
    nstg = 2;
elseif method == 3
    W = 1/2;
    w = 1; 
elseif method == 4
    W = (1/24)*[7 -1; 13 5];
    w = [1/2; 1/2];
    nstg = 2;    
end

% Stabilization parameter
if any(method ==[3:4])
    % Soulaimani and Fortin (1994), Codina (2000)
    inv_W = inv(W);
    tau = (inv_W/dt + (2*a/h + 4*nu/h^2 + sigma))'\inv_W;
    disp(' ')
    disp('Stabilization matrix for multistage scheme:')
    disp(tau)
end

[A,B] = System(M,K,C,Ka,Dif,dt,method,nu,sigma,W,w,tau);
 
for n=1:nStep 
    if method == 1 || method == 3

        du = [A , ADir' ; ADir  zDir]\[B*u(:,n) ; bDir];

        u(:,n+1) = u(:,n) + du(1:nNodes,1);
    
    elseif method == 2 || method == 4
        
        ADir1 = [ADir 0*ADir; 0*ADir ADir];
        bDir1 = [bDir; bDir];
        nDir = length(bDir1);
        zDir = zeros(nDir,nDir);
        
        du = [A , ADir1' ; ADir1  zDir]\[B*u(:,n) ; bDir1];
        du = reshape (du(1:nstg*nNodes),nNodes,nstg);
        u(:,n+1) = u(:,n) + sum(du,2);
    end
end

toc

% Ploting the results
ploting(X,u,nStep,nx,ny,p);


















