function fn = prescFlow(X,T,TB,bType,bVal,referenceElement)
% fn = prescFlow(X,T,TB,bType,bVal,referenceElement)
% Defines Neumann boundary conditions.
% Input:
% X: nodal coordinates.
% T: connectivities.
% TB: boundary connectivities
% bType: boundary condition type.
% bVal: boundary condition value.
% referenceElement: type of elements.
%
% Output:
% fn: force vector with Neumann values.

T_boundary = OutflowBoundary(T,TB,bType);
p = referenceElement.degree; 

% 1D quadrature
ngaus = 3; 
zgp = [-sqrt(15)/5; 0; sqrt(15)/5]; 
wgp = [5/9   8/9   5/9];

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

% Normal to element considered in every boundary.
bDir  = [-1,-1,1,1,-1];         

fn = zeros(nPt,1);

% Loop on elements
for i = 1:nElem
    j  = T_boundary(i,1);
    Te = T_boundary(i,4:end); 
    P1 = X(T_boundary(i,4),:); 
    P2 = X(T_boundary(i,end),:); 
    h = norm(P2 - P1);
    N = ShapeFunc_1D(zgp,p);

    fne = zeros(size(N,2),1);
    
    for ig = 1:ngaus
        N_ig  = N(ig,:);
        dvolu = wgp(ig)*h/2;
        % Contribution to element matrix
        fne = fne + bDir(j)*N_ig'*bVal(j)*dvolu;
    end
    % Assembly 
    fn(Te) = fn(Te) + fne; 
end


function T_boundary = OutflowBoundary(T,TB,bType)

n = [-1 0;-1 0;0 1;1 0;0 -1];
ind = 1;
T_bd = zeros(size(T,1),2+size(TB{1},2));

for i = 1:length(TB)
    if (bType(i) == 2)
        for j = 1:size(TB{i},1)
            T_bd(ind,:) = [i, n(i,:), TB{i}(j,2:end)];
            ind = ind+1;
        end
    end
end

T_boundary = T_bd(1:ind-1,:);


function N = ShapeFunc_1D(zgp_1D,p)

xi = zgp_1D;

if p == 1; N = [0.5*(1-xi)    0.5*(xi+1)];
else       N = [0.5*(xi-1).*xi    (1-xi.^2)    0.5*(xi+1).*xi];
end
