function [TL,TR] = GLSMethod(XP,TP,tau,referenceElement)
% [K,G,f] = StokesSystem(X,T,XP,TP,referenceElement)
% Matrices K, G and r.h.s vector f obtained after discretizing a Stokes problem
%
% X,T: nodal coordinates and connectivities for velocity
% XP,TP: nodal coordinates and connectivities for pressure
% referenceElement: reference element properties (quadrature, shape functions...)

ngaus = referenceElement.ngaus;
wgp = referenceElement.GaussWeights;
NP = referenceElement.NP; 
NPxi = referenceElement.NPxi;
NPeta = referenceElement.NPeta; 

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

% Number of nodes
nPt_P = size(XP,1);

% Number of degrees of freedom 
nedofP = nenP;
ndofP = nPt_P; 

TL = zeros(ndofP,ndofP);
TR = zeros(ndofP,1);

% Loop on elements
for ielem = 1:nElem
    % Global number of the nodes in element ielem
    TPe = TP(ielem,:); 
    % Coordinates of the nodes in element ielem
    XPe = XP(TPe,:);
    % Degrees of freedom in element ielem

    % Element matrices
    [TLe,TRe] = EleMatGLS(XPe,nedofP,ngaus,wgp,NP,NPxi,NPeta,tau);
    
    % Assemble the element matrices
    TL(TPe, TPe) = TL(TPe, TPe) + TLe;
    TR(TPe) = TR(TPe) + TRe;
end

function [TLe,TRe] = EleMatGLS(XPe,nedofP,ngaus,wgp,NP,NPxi,NPeta,tau)
% [TLe,TRe] = EleMatStokes(Xe,ngeom,nedofV,nedofP,ngaus,wgp,N,Nxi,Neta,NP)

TLe = zeros(nedofP,nedofP);
TRe = zeros(nedofP,1);
% Loop on Gauss points 
for ig = 1:ngaus
    NP_ig = NP(ig,:); 
    NPxi_ig = NPxi(ig,:);
    NPeta_ig = NPeta(ig,:);
    Jacob = [
        NPxi_ig*(XPe(:,1))	 NPxi_ig*(XPe(:,2))
        NPeta_ig*(XPe(:,1))  NPeta_ig*(XPe(:,2))
        ];
    dvolu = wgp(ig)*det(Jacob);
    res = Jacob\[NPxi_ig;NPeta_ig];
  

    TLe = TLe + tau*(res'*res)*dvolu; 
    x_ig = NP_ig*XPe; 
    f_igaus = SourceTerm(x_ig); 
    TRe = TRe + tau*res'*f_igaus*dvolu; 
end