function [K,G,f] = CreMat(X,IEN,XP,IENP,elem) 
% [K,G,f] = CreMat(X,IEN,XP,IENP,elem) 
% This function computes viscosity matrix K, gradient matrix G
% and vector f (source term) obtained by discretizing the Galerkin
% weak form of the Stokes problem in 2D using finite elements.
%
% Input:
%
%   X:      nodal coordinates (velocity)
%   IEN:    connectivities (velocity)
%   XP:     nodal coordinates (pressure)
%   IENP:   connectivities (pressure)
%   elem:   type of element (0: quadrilateral, 1: triangle)
%


% Total number of elements and element node's number
% for velocity and pressure
[numel,nen] = size(IEN); 
[numelP,nenP] = size(IENP);
% Total number of nodes
if elem == 1 & nen == 4 % MINI
    numnp = size(X,1) + numel;
else
    numnp = size(X,1);     
end
% Degrees of freedom
nunk  = 2*numnp; ndofn = 2*nen;
nunkP = size(XP,1);

% Number of Gauss points used in the numerical quadrature (ngaus)
% and number of nodes to interpolate the geometry (ngeom)
if elem == 0
    if nen == 4
        ngaus = 4; ngeom = 4;
    elseif nen == 9
        ngaus = 9; ngeom = 9;
    end
else
    if nen == 3
        ngaus = 3; ngeom = 3;
    elseif nen == 6 
        ngaus = 4; ngeom = 6;
    elseif nen == 4 
        ngaus = 7; ngeom = 3;
    end
end

% Quadrature and shape functions on the Gauss points
[pospg,wpg] = Quadrature(elem,ngaus);
[N,Nxi,Neta] = ShapeFunc(elem,nen,pospg);
[NP,NxiP,NetaP] = ShapeFunc(elem,nenP,pospg);
clear NxiP NetaP; pack;


% Allocates storage for matrices
if nen <= 4
    K = spalloc(nunk,nunk,10*nunk); 
    G = spalloc(nunkP,nunk,10*nunk);   
else
    K = spalloc(nunk,nunk,20*nunk); 
    G = spalloc(nunkP,nunk,20*nunk);     
end
f = zeros(nunk,1); 


% Loop on elements
for ielem = 1:numel 
    % Te: current velocity element 
    Te = reshape([2*IEN(ielem,:)-1; 2*IEN(ielem,:)],1,ndofn); 
    % TeP: current pressure element 
    TeP = IENP(ielem,:);
    % Xe: element nodes' coordinates
    Xe = X(IEN(ielem,1:ngeom),:); 
    % Element matrices
    [Ke,Ge,fe] = EleMat(Xe,ngeom,ndofn,pospg,wpg,N,Nxi,Neta,nenP,NP); 
    % Assembly
    K(Te,Te) = K(Te,Te) + Ke; 
    G(TeP,Te)= G(TeP,Te)+ Ge; 
    f(Te) = f(Te) + fe; 
    clear Ke Ge fe; 
end

K = sparse(K);
G = sparse(G);
