%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% This file is part of NS2DDV. %
% %
% Copyright(C) 2011-2018 C. Calgaro (caterina.calgaro@math.univ-lille1.fr) %
% E. Creusé (emmanuel.creuse@math.univ-lille1.fr) %
% T. Goudon (thierry.goudon@inria.fr) %
% A. Mouton (alexandre.mouton@math.univ-lille1.fr) %
% %
% NS2DDV is free software: you can redistribute it and/or modify it under the terms %
% of the GNU General Public License as published by the Free Software Foundation, %
% either version 3 of the License, or (at your option) any later version. %
% %
% NS2DDV is distributed in the hope that it will be useful, but WITHOUT ANY %
% WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A %
% PARTICULAR PURPOSE. See the GNU General Public License for more details. %
% %
% You should have received a copy of the GNU General Public License along with %
% NS2DDV. If not, see <http://www.gnu.org/licenses/>. %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function[e, be, te] = edge_descriptor(t, PARAMETERS)
% INPUT
% t List of P1 triangles described by P1 nodes
% PARAMETERS List of simulation parameters
%
% OUTPUT
% e Edge descriptor
% be Bound edge descriptor
% te Triangle descriptor by edges
% For each edge
% e(1:2,i) is the list of P1 nodes that are the extremities
% e(3:4,i) are the left and right cells that are separated by the edge
% e(5,i) is the subdomain index in which the edge is included
% e(4,i) < 1 if e(:,i) describes a bound edge
% For each bound edge
% be(1:2,i) is the list of P1 nodes that are the extremities
% be(3,i) is the cell that is separated from the exterior by the bound edge
% be(4,i) is dummy
% be(5,i) is the index of the bound edge in the list e above
% For each triangle
% te(k,i) is the index of the edge in the list e above that is opposed to the P1 node t(k,i) in the triangle
nt = size(t,2);
ne = 3*nt;
e = [];
be = [];
te = [];
% We extract the list of edges from the description of the cells by nodes
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% We consider two temporary edges lists: temp1 will contains the edges with vertex indices (i1,i2) satisfying i1 < i2 and
% temp2 will contains the edges with vertex indices (i1,i2) satisfying i1 > i2
% Each edge can appear only one time in temp1
% Each edge can appear only one time in temp2
% An interior edge appears one time in temp1 and one time in temp2
% A bound edge appears one time in the reunion of temp1 and temp2
% In temp2, we permute i1 and i2 before storing the edge in order to have temp2(*,1) < temp2(*,2)
% ==> temp1 and temp2 are not completely fullfilled after having read all the cells
temp1_1 = zeros(nt,5);
temp1_2 = zeros(nt,5);
temp1_3 = zeros(nt,5);
temp2_1 = zeros(nt,5);
temp2_2 = zeros(nt,5);
temp2_2 = zeros(nt,5);
switch PARAMETERS.PARALLELIZATION.TOOLBOX
case {'SERIAL'}
for ke=1:nt
tloc = t(1:3,ke);
if (tloc(1) < tloc(2))
temp1_1(ke,:) = [ ...
tloc(1), ... % First extremity of the edge
tloc(2), ... % Second extremity of the edge
ke, ... % Index of involved triangular cell
tloc(3), ... % Keep in mind the third vertex of the triangle
tloc(3)];
else
temp2_1(ke,:) = [ ...
tloc(2), ... % First extremity of the edge
tloc(1), ... % Second extremity of the edge
ke, ... % Index of involved triangular cell
tloc(3), ... % Keep in mind the third vertex of the triangle
tloc(3)];
end
if (tloc(2) < tloc(3))
temp1_2(ke,:) = [ ...
tloc(2), ... % First extremity of the edge
tloc(3), ... % Second extremity of the edge
ke, ... % Index of involved triangular cell
tloc(1), ... % Keep in mind the third vertex of the triangle
tloc(1)];
else
temp2_2(ke,:) = [ ...
tloc(3), ... % First extremity of the edge
tloc(2), ... % Second extremity of the edge
ke, ... % Index of involved triangular cell
tloc(1), ... % Keep in mind the third vertex of the triangle
tloc(1)];
end
if (tloc(3) < tloc(1))
temp1_3(ke,:) = [ ...
tloc(3), ... % First extremity of the edge
tloc(1), ... % Second extremity of the edge
ke, ... % Index of involved triangular cell
tloc(2), ... % Keep in mind the third vertex of the triangle
tloc(2)];
else
temp2_3(ke,:) = [ ...
tloc(1), ... % First extremity of the edge
tloc(3), ... % Second extremity of the edge
ke, ... % Index of involved triangular cell
tloc(2), ... % Keep in mind the third vertex of the triangle
tloc(2)];
end
end
case {'PCT'}
parfor ke=1:nt
tloc = t(1:3,ke);
if (tloc(1) < tloc(2))
temp1_1(ke,:) = [ ...
tloc(1), ... % First extremity of the edge
tloc(2), ... % Second extremity of the edge
ke, ... % Index of involved triangular cell
tloc(3), ... % Keep in mind the third vertex of the triangle
tloc(3)];
else
temp2_1(ke,:) = [ ...
tloc(2), ... % First extremity of the edge
tloc(1), ... % Second extremity of the edge
ke, ... % Index of involved triangular cell
tloc(3), ... % Keep in mind the third vertex of the triangle
tloc(3)];
end
if (tloc(2) < tloc(3))
temp1_2(ke,:) = [ ...
tloc(2), ... % First extremity of the edge
tloc(3), ... % Second extremity of the edge
ke, ... % Index of involved triangular cell
tloc(1), ... % Keep in mind the third vertex of the triangle
tloc(1)];
else
temp2_2(ke,:) = [ ...
tloc(3), ... % First extremity of the edge
tloc(2), ... % Second extremity of the edge
ke, ... % Index of involved triangular cell
tloc(1), ... % Keep in mind the third vertex of the triangle
tloc(1)];
end
if (tloc(3) < tloc(1))
temp1_3(ke,:) = [ ...
tloc(3), ... % First extremity of the edge
tloc(1), ... % Second extremity of the edge
ke, ... % Index of involved triangular cell
tloc(2), ... % Keep in mind the third vertex of the triangle
tloc(2)];
else
temp2_3(ke,:) = [ ...
tloc(1), ... % First extremity of the edge
tloc(3), ... % Second extremity of the edge
ke, ... % Index of involved triangular cell
tloc(2), ... % Keep in mind the third vertex of the triangle
tloc(2)];
end
end
otherwise
error(sprintf('Unknown value of PARAMETERS.PARALLELIZATION.TOOLBOX\n'));
end
temp1 = [temp1_1; temp1_2; temp1_3];
newtemp11 = sortrows(temp1);
for i=1:size(newtemp11,1)
if (newtemp11(i,1) > 0)
break;
end
end
newtemp1 = newtemp11(i:size(newtemp11,1),:);
temp2 = [temp2_1; temp2_2; temp2_3];
newtemp22 = sortrows(temp2);
for i=1:size(newtemp22,1)
if (newtemp22(i,1) > 0)
break;
end
end
newtemp2 = newtemp22(i:size(newtemp22,1),:);
clear temp1;
clear temp1_1;
clear temp1_2;
clear temp1_3;
clear newtemp11;
clear temp2;
clear temp2_1;
clear temp2_2;
clear temp2_3;
clear newtemp22;
tempedges = zeros(ne,8);
n1 = 1;
n2 = 1;
%==> The n1 first lines of newtemp1 and the n2 first lines of newtemp2 are made of 0.
% We skip these lines.
% We fill the 8 first columns of edges
i = 1;
while ((n1 <= size(newtemp1,1)) || (n2 <= size(newtemp2,1)))
if (n1 > size(newtemp1,1))
% newtemp1 has been completely scanned
% The data entirely comes from newtemp2
tempedges(i,1:3) = newtemp2(n2,1:3);
tempedges(i,5:6) = newtemp2(n2,4:5);
n2 = n2+1;
i = i+1;
elseif (n2 > size(newtemp2,1))
% newtemp2 has been completely scanned
% The data entirely comes from newtemp1
tempedges(i,1:3) = newtemp1(n1,1:3);
tempedges(i,5:6) = newtemp1(n1,4:5);
n1 = n1+1;
i = i+1;
elseif ((newtemp1(n1,1) == newtemp2(n2,1)) && (newtemp1(n1,2) == newtemp2(n2,2)))
% the edges from newtemp1 and newtemp2 coincide --> we treat an interior edge
% The extremities come from newtemp1
tempedges(i,1:2) = newtemp1(n1,1:2);
% The index of the cell on the left side (K) of the edge comes from newtemp1
tempedges(i,3) = newtemp1(n1,3);
% The index of the cell on the right side (L) of the edge comes from newtemp2
tempedges(i,4) = newtemp2(n2,3);
% The indices of preceeding and following vertices in K come from newtemp1
tempedges(i,5:6) = newtemp1(n1,4:5);
% The indices of preceeding and following vertices in L come from newtemp1
tempedges(i,7:8) = newtemp2(n2,4:5);
i = i+1;
n1 = n1+1;
n2 = n2+1;
elseif ((newtemp1(n1,1) == newtemp2(n2,1)) && (newtemp1(n1,2) < newtemp2(n2,2)))
% The line from newtemp1 preceeds the line from newtemp2 in the sorting convention
% --> The data entirely comes from newtemp1
tempedges(i,1:3) = newtemp1(n1,1:3);
tempedges(i,5:6) = newtemp1(n1,4:5);
i = i+1;
n1 = n1+1;
elseif (newtemp1(n1,1) < newtemp2(n2,1))
% The line from newtemp1 preceeds the line from newtemp2 in the sorting convention
% --> The data entirely comes from newtemp1
tempedges(i,1:3) = newtemp1(n1,1:3);
tempedges(i,5:6) = newtemp1(n1,4:5);
i = i+1;
n1 = n1+1;
else
% The line from newtemp2 preceeds the line from newtemp1 in the sorting convention
% --> The data entirely comes from newtemp2
tempedges(i,1:3) = newtemp2(n2,1:3);
tempedges(i,5:6) = newtemp2(n2,4:5);
i = i+1;
n2 = n2+1;
end
end
clear newtemp1;
clear newtemp2;
% Extract the real list of edges
ne = 1;
while (~((tempedges(ne,1) == 0) && (tempedges(ne,2) == 0)))
ne = ne+1;
end
ne = ne-1;
etemp = [tempedges(1:ne,1:2)';
(-2*(tempedges(1:ne,4) < ones(ne,1))+ones(ne,1))';
tempedges(1:ne,3:4)'];
clear tempedges;
% We correct the orientation of the edges in order to fit with the orientation of cells
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
et = zeros(ne,5);
switch PARAMETERS.PARALLELIZATION.TOOLBOX
case {'SERIAL'}
for i=1:ne
Kstar = etemp(1,i);
Lstar = etemp(2,i);
K = etemp(4,i);
% We verify if the edge (xK*,xL*) is correctly oriented in cell K
% If it is not the case, we switch the indices K* and L* in the edges list
edge_is_OK = (((Kstar == t(1,K)) && (Lstar == t(2,K))) || ...
((Kstar == t(2,K)) && (Lstar == t(3,K))) || ...
((Kstar == t(3,K)) && (Lstar == t(1,K))));
et(i,:) = [ ...
etemp(1,i)*edge_is_OK+etemp(2,i)*(1-edge_is_OK), ...
etemp(2,i)*edge_is_OK+etemp(1,i)*(1-edge_is_OK), ...
etemp(3:5,i)'];
end
case {'PCT'}
parfor i=1:ne
Kstar = etemp(1,i);
Lstar = etemp(2,i);
K = etemp(4,i);
% We verify if the edge (xK*,xL*) is correctly oriented in cell K
% If it is not the case, we switch the indices K* and L* in the edges list
edge_is_OK = (((Kstar == t(1,K)) && (Lstar == t(2,K))) || ...
((Kstar == t(2,K)) && (Lstar == t(3,K))) || ...
((Kstar == t(3,K)) && (Lstar == t(1,K))));
et(i,:) = [ ...
etemp(1,i)*edge_is_OK+etemp(2,i)*(1-edge_is_OK), ...
etemp(2,i)*edge_is_OK+etemp(1,i)*(1-edge_is_OK), ...
etemp(3:5,i)'];
end
otherwise
error(sprintf('Unknown value of PARAMETERS.PARALLELIZATION.TOOLBOX\n'));
end
e = et';
clear etemp;
nbe = 0;
for i=1:ne
if (e(5,i) < 1)
nbe = nbe+1;
end
end
be = zeros(5,nbe);
k = 1;
for i=1:ne
if (e(5,i) < 1)
be(:,k) = e(:,i);
be(5,k) = i;
k = k+1;
end
end
% The full list of edges is built. We now add the description of cells by edges.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
tenosort = zeros(3,nt);
countedge_triangle = zeros(1,nt);
for i=1:ne
K = e(4,i);
L = e(5,i);
countedge_triangle(K) = countedge_triangle(K)+1;
tenosort(countedge_triangle(K),K) = i;
if (L > 0)
countedge_triangle(L) = countedge_triangle(L)+1;
tenosort(countedge_triangle(L),L) = -i;
end
end
clear countedge_triangle;
tet = zeros(nt,3);
switch PARAMETERS.PARALLELIZATION.TOOLBOX
case {'SERIAL'}
for ke=1:nt
for ip=1:3
inode = t(ip,ke);
for ie=1:3
iedge = abs(tenosort(ie,ke));
if (~(inode == e(1,iedge)) && ~(inode == e(2,iedge)))
% inode is the vertex that is opposite to the edge iedge in the triangle ke
tet(ke,ip) = iedge;
end
end
end
end
case {'PCT'}
parfor ke=1:nt
for ip=1:3
inode = t(ip,ke);
for ie=1:3
iedge = abs(tenosort(ie,ke));
if (~(inode == e(1,iedge)) && ~(inode == e(2,iedge)))
% inode is the vertex that is opposite to the edge iedge in the triangle ke
tet(ke,ip) = iedge;
end
end
end
end
otherwise
error(sprintf('Unknown value of PARAMETERS.PARALLELIZATION.TOOLBOX\n'));
end
te = tet';
clear tenosort;
clear tet;
if (min(te) <= 0)
error(sprintf('Problem while building the descriptor by edges of triangles.\n'));
end
end