function [M,K,K1,C,C1] = FEM_matrices(X,T,velo,referenceElement) 


% reference element information
nen = referenceElement.nen; 
ngaus = referenceElement.ngaus; 
wgp = referenceElement.GaussWeights; 
N = referenceElement.N; 
Nxi = referenceElement.Nxi; 
Neta = referenceElement.Neta; 

% Number of nodes and elements
nPt = size(X,1); 
nElem = size(T,1); 

M = zeros(nPt);
K = zeros(nPt); 
K1 = zeros(nPt);
C = zeros(nPt);
C1 = zeros(nPt);

% Loop on elements
for ielem=1:nElem
    Te = T(ielem,:); 
    Xe = X(Te,:); 
    [Me,Ke,Ke1,Ce,Ce1] = EleMat(Xe,velo,nen,ngaus,wgp,N,Nxi,Neta);
    % Assembly
    M(Te,Te) = M(Te,Te) + Me; 
    K(Te,Te) = K(Te,Te) + Ke; 
    K1(Te,Te) = K1(Te,Te) + Ke1;
    C(Te,Te) = C(Te,Te) + Ce; 
    C1(Te,Te) = C1(Te,Te)+Ce1;
end



function [Me,Ke,Ke1,Ce,Ce1] = EleMat(Xe,velo,nen,ngaus,wgp,N,Nxi,Neta)
%

Me = zeros(nen);
Ke = zeros(nen);
Ke1 = zeros(nen);
Ce = zeros(nen);
Ce1 = zeros(nen);


% Loop on Gauss points 
for ig = 1:ngaus
    N_ig = N(ig,:);
    Nxi_ig = Nxi(ig,:);
    Neta_ig = Neta(ig,:);
    Jacob = [Nxi_ig*(Xe(:,1))	Nxi_ig*(Xe(:,2))
             Neta_ig*(Xe(:,1))	Neta_ig*(Xe(:,2))];
    dvolu = wgp(ig)*det(Jacob);
    res = Jacob\[Nxi_ig;Neta_ig];
    Nx = res(1,:);
    Ny = res(2,:);
    ax = velo(1); ay = velo(2); 
    
    Me = Me + N_ig'*N_ig*dvolu; 
    aGradN = ax*Nx + ay*Ny; 
    GradN = Nx+Ny;
    Ke = Ke + aGradN'*aGradN*dvolu;
    Ke1 = Ke1 + GradN'*GradN*dvolu;
    Ce = Ce + N_ig'*aGradN*dvolu;
    Ce1 = Ce1 + aGradN'*N_ig*dvolu;
end

