function [C,fc] = ConvectionMatrix(X,T,referenceElement,velo)
% Convective matrix obtained after discretizing a Navier-Stokes problem
%
% X,T: nodal coordinates and connectivities for velocity
% referenceElement: reference element properties (quadrature, shape functions...)


elem = referenceElement.elemV;
ngaus = referenceElement.ngaus;
wgp = referenceElement.GaussWeights;
N = referenceElement.N;
Nxi = referenceElement.Nxi;
Neta = referenceElement.Neta;
ngeom = referenceElement.ngeom;
meth = referenceElement.iter_meth;

% Number of elements and number of nodes in each element
[nElem,nenV] = size(T); 

% Number of nodes
nPt_V = size(X,1);
if elem == 11
    nPt_V = nPt_V + nElem; 
end

% Number of degrees of freedom 
nedofV = 2*nenV; 
ndofV = 2*nPt_V; 

C = zeros(ndofV,ndofV);
fc = zeros(ndofV,1);

% Loop on elements
for ielem = 1:nElem
    % Global number of the nodes in element ielem
    Te = T(ielem,:);
    % Coordinates of the nodes in element ielem
    Xe = X(Te(1:ngeom),:);
    % Elemental Velocity
    veloe = velo(Te,:);
    % Degrees of freedom in element ielem
    Te_dof = reshape([2*Te-1; 2*Te],1,nedofV);
    
    % Convective Element matrix
    [Ce,fce] = EleMatC(Xe,ngeom,nedofV,ngaus,wgp,N,Nxi,Neta,veloe,meth);
    
    % Assemble the element matrices
    C(Te_dof, Te_dof) = C(Te_dof, Te_dof) + Ce;
    fc(Te_dof) = fc(Te_dof) + fce;
end

function [Ce,fce] = EleMatC(Xe,ngeom,nedofV,ngaus,wgp,N,Nxi,Neta,veloe,meth)

Ce = zeros(nedofV,nedofV);
fce = zeros(nedofV,1);

% Loop on Gauss points 
for ig = 1:ngaus
    N_ig    = N(ig,:);
    Nxi_ig  = Nxi(ig,:);
    Neta_ig = Neta(ig,:);
    Jacob = [
        Nxi_ig(1:ngeom)*(Xe(:,1))	Nxi_ig(1:ngeom)*(Xe(:,2))
        Neta_ig(1:ngeom)*(Xe(:,1))	Neta_ig(1:ngeom)*(Xe(:,2))
        ];
    dvolu = wgp(ig)*det(Jacob);
    res = Jacob\[Nxi_ig;Neta_ig];
    vel_nod = N_ig*veloe;
    uGradN = vel_nod*res;
%     GradU = res*veloe; % gradient values in gauss points
%     uGradU = uGradN*veloe;
%     GradU_N = [GradU(1,1)*N_ig GradU(2,1)*N_ig;GradU(1,2)*N_ig GradU(2,2)*N_ig];
%     GradUU = res*vel_nod*N_ig;
    
	Ngp = [reshape([1;0]*N_ig,1,nedofV); reshape([0;1]*N_ig,1,nedofV)];
    % Convective Term reshaped
    uGradN_rshp = [reshape([1;0]*uGradN,1,nedofV); reshape([0;1]*uGradN,1,nedofV)];
%     GradU_N_1 = [reshape([1;0]*GradU(1,1)*N_ig,1,nedofV); reshape([0;1]*GradU(2,2)*N_ig,1,nedofV)];
%     GradU_N_2 = [reshape([0;1]*GradU(2,1)*N_ig,1,nedofV); reshape([1;0]*GradU(1,2)*N_ig,1,nedofV)];
%     GradU_N = GradU_N_1 + GradU_N_2;
%     Grad_rshp = reshape(res,1,[])';
    Ce = Ce + Ngp'*uGradN_rshp*dvolu;
    if 0==1 % meth==1
        Ce = Ce + Ngp'*Grad_rshp*vel_nod*Ngp*dvolu;
        fce = fce + Ngp'*uGradN_rshp*reshape(veloe,1,[])'*dvolu;
    else
        Ce = Ce + Ngp'*uGradN_rshp*dvolu;
    end

end

