%==========================================================================
%        This code solves the problems related to the third question
%      described by the coupling of three equations involving u,F and G
%==========================================================================
clear; close all; clc

addpath('Func_ReferenceElement')
%==========================================================================
% Definition Material parameters
%==========================================================================
   nu = 10^3;theta = 1/2;D_F = 5;sigma_F = 0.25;
     D_G = 15;sigma_G = 2;sigma_GF = 0.5;
%==========================================================================
% Element type and interpolation degree
%=========================================================================
% (0: quadrilaterals, 1: triangles, 11: triangles with bubble function
elemV = 0; degreeV = 1; degreeP = 1;
% elemV = 1; degreeV = 2; degreeP = 1;
% elemV = 11; degreeV = 1;  degreeP = 1;
if elemV == 11
    elemP = 1;
else
    elemP = elemV;
end
referenceElement = SetReferenceElementStokes(elemV,degreeV,elemP,degreeP);
%==========================================================================
%Introduction of Polar parameters according to the provided domain 
%=========================================================================
Nr = input('Number of elements on the Radial direction (default: 20)= ');
Ntheta = input('Number of elements on the Theta direction (default: 10) = ');
if isempty(Nr)
    Nr = 20;
end
if isempty(Ntheta)
    Ntheta = 10;
end
% For the sake of utilizing the CreateMeshes function
nx = Ntheta;
ny = Nr;

[X,T,XP,TP,alpha] = CreateMeshes(nx,ny,referenceElement);
% [X,T] = createMesh(nx,ny,degreeV);
figure; PlotMesh_1(T,X,elemV,'b-');
% figure; plot_Mesh(TP,XP,elemP,'r-');
numnp = size(X,1);

Xe_ref = referenceElement.Xe_ref;
[Tf,Tu] = boundaryMatrices(X,T,elemV,degreeV,Xe_ref);

% Matrices arising from the discretization (for solution of velocity)
% [Ku,G,fu] = StokesSystem(X,T,XP,TP,referenceElement);
[K_u,G,f_u] = StokesSystem2(X,T,XP,TP,referenceElement);
K_u = nu*K_u;
ndofV = size(K_u,1);
% [ndofP,ndofV] = size(G);

% Matrix and r.h.s vector to impose Dirichlet boundary conditions
[A_DirBC_u, nDir_u, nodesDirBC_u, Dir_u, confined] = BC(nx,ny,ndofV,degreeV,alpha);
b_DirBC_u = Dir_u(:,2);

Ku_tot = K_u + Tu;
Ku_tot(Dir_u(:,1),:) = 0;
Ku_tot(:,Dir_u(:,1)) = 0;
Ku_tot(Dir_u(:,1),Dir_u(:,1)) = eye(nDir_u);

Atot_u = Ku_tot; % From stokes 
%==========================================================================
% COMPUTATION OF THE MATRICES (for solution of F and G)
%==========================================================================
% Number of Gauss points (numerical quadrature)
ngaus=4;
% Quadrature
[pospg,wpg] = Quadrature(elemV,ngaus);
% Shape Functions
[N,Nxi,Neta] = ShapeFunc(elemV,degreeV,pospg);
% Matrices obtained by discretizing the Galerkin weak-form
disp ('Computation of mass matrix M, from the term (w,F)')
M = CreMassMat(X,T,pospg,wpg,N,Nxi,Neta);
disp ('Computation of stiffness matrix K, from the term(grad(w),grad(F))');
K = CreStiffMat(X,T,pospg,wpg,N,Nxi,Neta);

% Input for the  Transient solution
t_end = input('Insert End time or press enter for a complete revolution)=  ');
nstep = input('Number of time steps (default: 100)= ');
if isempty(t_end)
    t_end = 2*pi;
end
if isempty(nstep)
    nstep = 120;
end
dt = t_end/nstep;

[F, Accd_F, bccd_F, nDir_F] = BC_F(nx,ny,numnp,nstep,X);
veloVect(:,1) = zeros(ndofV,1);
veloVect(Dir_u(:,1)) = Dir_u(:,2);

G = zeros(numnp,nstep+1);
A_G = M + theta*D_G*K*dt + theta*sigma_G*M*dt;
B_G = -D_G*K*dt - sigma_G*M*dt;
C_G = sigma_GF*M*dt;
f_G = zeros(numnp,1);
Atot_G = A_G;
[L2,U2] = lu(Atot_G);
%==========================================================================
%                             TRANSIENT SOLUTION
%==========================================================================
tol = 10^-6;
for n = 1:nstep
    veloInc = 1;  FInc = 1; iter = 0; Fsol = F(:,n);
    %===================Begin the loop for the iterative solution=========
    while veloInc>=tol   %   Check the solution of velocity
        iter = iter + 1;
        f_u = -Tf*Fsol(:,iter);
        for i =1:size(K_u,1)
            fu_tot(i,1) = f_u(i,1)-K_u(i,Dir_u(:,1))*b_DirBC_u;
        end
        for i = 1:nDir_u
            fu_tot(Dir_u(i,1)) = Dir_u(i,2);
        end
        %============== Retriev the Atot_u from stokes ===================
        veloVect(:,iter+1) = Atot_u\fu_tot;  
        velo_1 = veloVect(:,iter+1); velo = reshape(velo_1,2,[])';
        disp ('Computation of convection matrix C, from (grad(w),F)');
        Conv = velo; % This is the velocity input required for F
        C = CreConvMat(X,T,Conv,pospg,wpg,N,Nxi,Neta);
        %===== Matrices for the Iterative solution of U and F==============
        A_F = M + theta*C*dt + theta*D_F*K*dt + theta*sigma_F*M*dt;
        B_F = M + (1-theta)*(-C*dt - D_F*K*dt - sigma_F*M*dt);
        f_F = zeros(numnp,1);
        %===============Resulting Total Matrix=============================
        Atot_F = [A_F Accd_F';Accd_F zeros(nDir_F,nDir_F)];
        [L1,U1] = lu(Atot_F);
        btot_F = [B_F*F(:,n)+ f_F; bccd_F];
        Lf = U1\(L1\btot_F);
        Fsol(:,iter+1) =  Lf(1:numnp);
        %=================Velocity solution increment using the norm=======
        veloInc = norm(veloVect(:,iter+1)-veloVect(:,iter));
        %===================End of the while Loop  ========================
    end
    velocity0(:,n) = veloVect(:,iter+1);
    velo_1 = velocity0(:,n);
    velocity = reshape(velo_1,2,[])';
    disp ('Computation of convection matrix C,from the term (grad(w),F)');
    Conv = velocity;
    C = CreConvMat(X,T,Conv,pospg,wpg,N,Nxi,Neta);
    %COMPUTATION OF MATRICES FOR THE TRANSIENT ANALYSIS
    disp (' MATRICES OF F');
    A_F = M + theta*C*dt + theta*D_F*K*dt + theta*sigma_F*M*dt;
    B_F = (-C*dt - D_F*K*dt - sigma_F*M*dt);
    f_F = zeros(numnp,1);
    % Total matrix (including boundary conditions)
    Atot_F = [A_F Accd_F';Accd_F zeros(nDir_F,nDir_F)];
    [L1,U1] = lu(Atot_F);
    btot_F = [B_F*F(:,n)+ f_F; bccd_F];
    aux_f =  U1\(L1\btot_F);
    aux_F = U1\(L1\btot_F);
    F(:,n+1) = F(:,n) + aux_F(1:numnp);
    
    % Solution for G
        %btot = [B_G*G(:,n) - theta*C_G*aux_f(1:numnp) + theta*C_G*F(:,n+1) + f_G];
        btot = [B_G*G(:,n) + theta*C_G*aux_f(1:numnp) + C_G*F(:,n) + f_G];
 
        
        aux_G  = U2\(L2\btot);
        G(:,n+1) = G(:,n) + aux_G(1:numnp);
    
end

disp(' ')
disp(sprintf('Maximum_F = %e',max(F(:,nstep+1))))
disp(sprintf('Minimum_F = %e',min(F(:,nstep+1))))

disp(' ')
disp(sprintf('Maximum_G = %e',max(G(:,nstep+1))))
disp(sprintf('Minimum_G = %e',min(G(:,nstep+1))))

%% Postprocess

figure(1)
nPt = size(X,1);
figure;
quiver(X(1:nPt,1),X(1:nPt,2),velocity(1:nPt,1),velocity(1:nPt,2));
hold on
axis equal; axis tight

figure(2)
PlotResults(X,T,velocity(:,1),referenceElement.elemV,referenceElement.degreeV)
title('Velocity componet X')
figure(3)
PlotResults(X,T,velocity(:,2),referenceElement.elemV,referenceElement.degreeV)
v = sqrt((velocity(:,1).^2)+(velocity(:,2).^2));
title('Velocity componet Y')
figure(4)
PlotResults(X,T,v,referenceElement.elemV,referenceElement.degreeV)


%F
if max(F(:,nstep+1))<100 &&  min(F(:,nstep+1))>-100
    % Solution at time t=t_end
    figure(5); clf;
    [xx,yy,sol] = MatSol(X,Ntheta,Nr,F(:,nstep+1));
    surface(xx,yy,sol);
    colorbar
    view(3)
    axis auto
    grid on;
    title('Actin density F')
end
pause(0.1);
%G
if max(G(:,nstep+1))<100 &&  min(G(:,nstep+1))>-100
    % Solution at time t=t_end
    figure(11); clf;
    [xx,yy,sol] = MatSol(X,Ntheta,Nr,G(:,nstep+1));
    surface(xx,yy,sol);
    view([40,30])
    grid on;
    title('Monomer density G')

end
