function [M,K,C,f] = femMatrices(X,T,av,s,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); 
C = zeros(nPt);
f = zeros(nPt,1);

% Loop on elements
for ielem=1:nElem
    Te = T(ielem,:); 
    Xe = X(Te,:); 
    ae = av(Te,:);
    se = s(Te,:);
    [Me,Ke,Ce,fe] = EleMat(Xe,ae,se,nen,ngaus,wgp,N,Nxi,Neta);
    % 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,ae,se,nen,ngaus,wgp,N,Nxi,Neta)

Me = zeros(nen);
Ke = zeros(nen);
Ce = 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];
    dNx = res(1,:);
    dNy = res(2,:);
    dN  = [dNx;dNy];
    a = N_ig*ae; 
    ax = a(1); 
    ay = a(2); 
    
    a_dN = ax*dNx + ay*dNy;
    Me = Me + N_ig'*N_ig*dvolu;
    Ce = Ce + N_ig'*a_dN*dvolu;
    Ke = Ke + dN'*dN*dvolu;
    fe = fe + N_ig'*mean(se)*dvolu;
end

