function [M,K,C,f] = FEM_matrices(X,T,Conv,referenceElement,nu) 


% 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); 
C = zeros(nPt);
f = zeros(nPt,1);
% Loop on elements
for ielem=1:nElem
    Te = T(ielem,:); 
    Xe = X(Te,:); 
    Conve = Conv(Te,:);
    [Me,Ke,Ce,fe] = EleMat(Xe,Conve,nen,ngaus,wgp,N,Nxi,Neta,nu);
    % Assembly
    M(Te,Te) = M(Te,Te) + Me; 
    K(Te,Te) = K(Te,Te) + Ke; 
    C(Te,Te) = C(Te,Te) + Ce;
    f(Te)=f(Te)+fe;
end



function [Me,Ke,Ce,fe] = EleMat(Xe,Conve,nen,ngaus,wgp,N,Nxi,Neta,nu)
%

Me = zeros(nen);
Ke = zeros(nen);
Ce = zeros(nen);
Ae = zeros(nen);
Be = zeros(nen);
fe=zeros(nen,1);
% 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,:);
    a = N_ig*Conve; ax = a(1); ay = a(2); 
    aGradN = (ax*Nx) + (ay*Ny);
    
    aux=N_ig*Xe;
    f_ig=SourceTerm(aux);
    
   
    
    Me = Me + N_ig'*N_ig*dvolu; 
    Ke = Ke + (nu*(Nx'*Nx+Ny'*Ny))*dvolu;
    Ce = Ce + N_ig'*aGradN*dvolu;
    fe = fe + N_ig'*(f_ig*dvolu);
    
   
end

