You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

257 lines
8.4 KiB

3 years ago
%--------------------------
% @Author: Jingqiao Hu
% @Date: 2022-01-24 18:50:51
% @LastEditTime: 2022-04-28 11:22:51
%--------------------------
function [c_edofMat, c_nodes, cbns, c_nid, c_dupB] = assemble_cvt_free(c_polygon,)
ncell = size(c_polygon, 1);
c_nodes = cell(ncell, 1); % macro nodes of each cell
c_nid = cell(ncell, 1); % macro nodes indices of each cell and face
c_dupB = cell(ncell, 1); % macro nodes indices of each cell and face
c_edofMat = cell(ncell, 1); % macro dofs of each cell
nodes = [];
% figure;
% NOTE: no parfor, sequence dependent!
for ele = 1 : ncell
c_poly = c_polygon{ele};
[c_nid_f, c_dupB_f, nodesCell] = edof_one_cell(c_poly);
c_nodes{ele} = nodesCell;
c_nid{ele} = c_nid_f;
c_dupB{ele} = c_dupB_f;
nodes = [nodes; nodesCell];
end
cbns = uniquetol(nodes, 1e-6, "Byrows", true);
% cbns = unique(nodes, "rows");
% scatter3(nodes(:,1),nodes(:,2),nodes(:,3)); hold on;
for ele = 1 : ncell
nodesCell = c_nodes{ele};
[~, idx] = ismembertol(nodesCell, cbns, 1e-5, 'Byrows', true);
% [~, idx] = ismember(nodesCell, cbns, 'rows');
if sum(idx < 1) > 0
error("here");
end
% NOTE: the sequence must conforms to Ke
edof0 = [3*idx-2, 3*idx-1, 3*idx]';
c_edofMat{ele} = edof0(:);
end
end
function [c_nid, c_dupB, nodesCell] = edof_one_cell(c_poly)
nface = size(c_poly, 1);
c_nid = cell(nface, 1);
c_dupB = cell(nface, 1);
nodesCell = [];
% NOTE: no parfor, sequence dependent!
% figure;
for i = 1 : nface
segsPerFace = c_poly{i}; % [n,6]
[~, nodesFace] = edof_one_face(segsPerFace);
% detect the duplicated nodes and remove them
[c_dupB_node, nodesUni] = unique_control_points(nodesFace);
nControlPnts = size(nodesUni, 1);
% nid saves the idx of saved nodes in nodesCell
if i==1
nodesCell = nodesUni;
nid = 1:nControlPnts;
else
% remove the duplicated nodes and add to nodesCell
[uniIDX_face, nid] = deal_duplicated(nodesCell, nodesUni);
nodesCell = [nodesCell; nodesUni(uniIDX_face,:)];
end
c_nid{i} = nid;
c_dupB{i} = c_dupB_node;
% scatter3( nodesUni(nid(:,2),1), nodesUni(nid(:,2),2), nodesUni(nid(:,2),3), 'filled'); hold on;
% x = segsPerFace(:,[1,4]);
% y = segsPerFace(:,[2,5]);
% z = segsPerFace(:,[3,6]);
% plot3(x',y',z','LineWidth',2); hold on;
end
% scatter3(nodesCell(:, 1), nodesCell(:, 2), nodesCell(:, 3), 'filled'); hold on;
end
% TODO: HOW TO build cbns on surface
function [nedof, ref_nodes] = edof_one_face(segsPerFace)
% detect end vertex polygon
vertex = segsPerFace(:, 1:3);
nseg = size(segsPerFace, 1);
if nseg>7 && nseg~=10
error("Side of Polygon > 7 or != 10 !");
% nseg
end
% s-patch
switch nseg
case 3
% 200,101,002,011,020,110
nvar = 6;
ref_nodes = zeros(nvar, 3);
ref_nodes([1,4,6],:) = vertex;
ref_nodes(2,:) = mean(vertex([1,2],:));
ref_nodes(3,:) = mean(vertex([1,3],:));
ref_nodes(5,:) = mean(vertex([2,3],:));
case 4
% 2000,1100,1010,1001,0200,
% 0110,0101,0020,0011,0002
nvar = 10;
ref_nodes = zeros(nvar, 3);
ref_nodes([1,5,8,10],:) = vertex;
ref_nodes(2,:) = mean(vertex([1,2],:));
ref_nodes(3,:) = mean(vertex([1,3],:)); %
ref_nodes(4,:) = mean(vertex([1,4],:));
ref_nodes(6,:) = mean(vertex([2,3],:));
ref_nodes(7,:) = mean(vertex([2,4],:)); %
ref_nodes(9,:) = mean(vertex([3,4],:));
case 5
nvar = 15;
ref_nodes = zeros(nvar, 3);
ref_nodes(1,:) = vertex(1,:);
ref_nodes(2,:) = mean(vertex([1,2],:));
ref_nodes(3,:) = mean(vertex([1,3],:));
ref_nodes(4,:) = mean(vertex([1,4],:));
ref_nodes(5,:) = mean(vertex([1,5],:));
ref_nodes(6,:) = vertex(2,:);
ref_nodes(7,:) = mean(vertex([2,3],:));
ref_nodes(8,:) = mean(vertex([2,4],:));
ref_nodes(9,:) = mean(vertex([2,5],:));
ref_nodes(10,:) = vertex(3,:);
ref_nodes(11,:) = mean(vertex([3,4],:));
ref_nodes(12,:) = mean(vertex([3,5],:));
ref_nodes(13,:) = vertex(4,:);
ref_nodes(14,:) = mean(vertex([4,5],:));
ref_nodes(15,:) = vertex(5,:);
case 6
nvar = 21;
ref_nodes = zeros(nvar, 3);
ref_nodes(1,:) = vertex(1,:);
ref_nodes(2,:) = mean(vertex([1,2],:));
ref_nodes(3,:) = mean(vertex([1,3],:));
ref_nodes(4,:) = mean(vertex([1,4],:)); %
ref_nodes(5,:) = mean(vertex([1,5],:));
ref_nodes(6,:) = mean(vertex([1,6],:));
ref_nodes(7,:) = vertex(2,:);
ref_nodes(8,:) = mean(vertex([2,3],:));
ref_nodes(9,:) = mean(vertex([2,4],:));
ref_nodes(10,:) = mean(vertex([2,5],:)); %
ref_nodes(11,:) = mean(vertex([2,6],:));
ref_nodes(12,:) = vertex(3,:);
ref_nodes(13,:) = mean(vertex([3,4],:));
ref_nodes(14,:) = mean(vertex([3,5],:));
ref_nodes(15,:) = mean(vertex([3,6],:)); %
ref_nodes(16,:) = vertex(4,:);
ref_nodes(17,:) = mean(vertex([4,5],:));
ref_nodes(18,:) = mean(vertex([4,6],:));
ref_nodes(19,:) = vertex(5,:);
ref_nodes(20,:) = mean(vertex([5,6],:));
ref_nodes(21,:) = vertex(6,:);
case 7
nvar = 28;
ref_nodes = zeros(nvar, 3);
ref_nodes(1,:) = vertex(1,:);
ref_nodes(2,:) = mean(vertex([1,2],:));
ref_nodes(3,:) = mean(vertex([1,3],:));
ref_nodes(4,:) = mean(vertex([1,4],:));
ref_nodes(5,:) = mean(vertex([1,5],:));
ref_nodes(6,:) = mean(vertex([1,6],:));
ref_nodes(7,:) = mean(vertex([1,7],:));
ref_nodes(8,:) = vertex(2,:);
ref_nodes(9,:) = mean(vertex([2,3],:));
ref_nodes(10,:) = mean(vertex([2,4],:));
ref_nodes(11,:) = mean(vertex([2,5],:));
ref_nodes(12,:) = mean(vertex([2,6],:));
ref_nodes(13,:) = mean(vertex([2,7],:));
ref_nodes(14,:) = vertex(3,:);
ref_nodes(15,:) = mean(vertex([3,4],:));
ref_nodes(16,:) = mean(vertex([3,5],:));
ref_nodes(17,:) = mean(vertex([3,6],:));
ref_nodes(18,:) = mean(vertex([3,7],:));
ref_nodes(19,:) = vertex(4,:);
ref_nodes(20,:) = mean(vertex([4,5],:));
ref_nodes(21,:) = mean(vertex([4,6],:));
ref_nodes(22,:) = mean(vertex([4,7],:));
ref_nodes(23,:) = vertex(5,:);
ref_nodes(24,:) = mean(vertex([5,6],:));
ref_nodes(25,:) = mean(vertex([5,7],:));
ref_nodes(26,:) = vertex(6,:);
ref_nodes(27,:) = mean(vertex([6,7],:));
ref_nodes(28,:) = vertex(7,:);
case 10
nvar = 55;
ref_nodes = zeros(55, 3);
idx = 1;
for i = 1:10
for j = i:10
ref_nodes(idx, :) = mean(vertex([i,j],:));
idx = idx + 1;
end
end
end
nedof = nvar * 3;
end
function [uniIDX_local, nid] = deal_duplicated(nodesGlobal, nodesLocal)
tol = 1e-5;
nid = [];
uniIDX_local = [];
k = size(nodesGlobal, 1) + 1;
for i = 1 : size(nodesLocal, 1)
[idx, ~] = find(abs(nodesGlobal(:, 1)-nodesLocal(i, 1)) < tol & ...
abs(nodesGlobal(:, 2)-nodesLocal(i, 2)) < tol & ...
abs(nodesGlobal(:, 3)-nodesLocal(i, 3)) < tol);
if isempty(idx)
uniIDX_local = [uniIDX_local; i];
nid = [nid; k];
k = k+1;
else
if length(idx) > 1
error("here");
end
nid = [nid; idx];
end
end
end
function [dupID, nodesUni] = unique_control_points(nodesFace)
% remove the duplicated nodes
nodesUni0 = uniquetol(nodesFace, 1e-5, "Byrows", true);
% reorder the unique nodes as original order
[nodesUni, uniID, ~] = intersect(nodesFace, nodesUni0, 'rows', 'stable');
% find the duplicated idx in nodesFace
tol = 1e-5;
dupID = cell(size(nodesUni, 1), 1);
for i = 1 : size(nodesUni, 1)
[idx, ~] = find(abs(nodesFace(:, 1)-nodesUni(i, 1)) < tol & ...
abs(nodesFace(:, 2)-nodesUni(i, 2)) < tol & ...
abs(nodesFace(:, 3)-nodesUni(i, 3)) < tol);
dupID{i} = idx; % length(idx) may be 3
end
end