lymph
PolyMesher.m
Go to the documentation of this file.
1 %> @file PolyMesher.m
2 %> @author Ilario Mazzieri
3 %> @brief Modified version of the original PolyMesher main file - version 1.1.
4 %>
5 %> The original version is taken from http://paulino.princeton.edu/software.html
6 %>------------------ PolyMesher version: 1.1 (Aug13) ---------------------%
7 %> Ref1: C Talischi, GH Paulino, A Pereira, IFM Menezes, %
8 %> "PolyMesher: A general-purpose mesh generator for polygonal %
9 %> elements written in Matlab", Struct Multidisc Optim, 2012, %
10 %> DOI 10.1007/s00158-011-0706-z %
11 %> %
12 %> Ref2: A Pereira, C Talischi, GH Paulino, IFM Menezes, MS Carvalho, %
13 %> "Implementation of fluid flow topology optimization in PolyTop", %
14 %> Struct Multidisc Optim, 2013, DOI XX.XXXX/XXXXXX-XXX-XXX-X %
15 %>-------------------------------------------------------------------------%
16 function [region] = PolyMesher(Domain,NElem,MaxIter,P)
17 if ~exist('P','var'), P=PolyMshr_RndPtSet(NElem,Domain); end
18 NElem = size(P,1);
19 Tol=5e-6; It=0; Err=1; c=1.5;
20 BdBox = Domain('BdBox'); PFix = Domain('PFix');
21 Area = (BdBox(2)-BdBox(1))*(BdBox(4)-BdBox(3));
22 Pc = P; %figure;
23 while(It<=MaxIter && Err>Tol)
24  Alpha = c*sqrt(Area/NElem);
25  P = Pc; %Lloyd's update
26  R_P = PolyMshr_Rflct(P,NElem,Domain,Alpha); %Generate the reflections
27  [P,R_P] = PolyMshr_FixedPoints(P,R_P,PFix); % Fixed Points
28  [Node,Element] = voronoin([P;R_P]); %Construct Voronoi diagram
29  [Pc,A] = PolyMshr_CntrdPly(Element,Node,NElem);
30  Area = sum(abs(A));
31  Err = sqrt(sum((A.^2).*sum((Pc-P).*(Pc-P),2)))*NElem/Area^1.5;
32  fprintf('It: %3d Error: %1.3e\n',It,Err); It=It+1;
33  if NElem<=2000, PolyMshr_PlotMsh(Node,Element,NElem); end;
34 end
35 [Node,Element] = PolyMshr_ExtrNds(NElem,Node,Element); %Extract node list
36 [Node,Element] = PolyMshr_CllpsEdgs(Node,Element,0.1); %Remove small edges
37 [Node,Element] = PolyMshr_RsqsNds(Node,Element); %Reoder Nodes
38 BC=Domain('BC',{Node,Element}); Supp=BC{1}; Load=BC{2}; %Recover BC arrays
39 % PolyMshr_PlotMsh(Node,Element,NElem,Supp,Load); %Plot mesh and BCs
40 
41 
42 
43 ne = length(Element);
44 elem_area = zeros(ne,1);
45 nedge = zeros(ne,1);
46 BBox = zeros(ne,4);
47 
48 coords_element = cell(1,ne);
49 max_kb = cell(1,ne);
50 
51 coord = Node;
52 
53 
54 for i = 1:length(Element)
55  nedge(i) = length(Element{i});
56  coords_element{i} = coord(Element{i},:);
57  x_min = min( coords_element{i}(:,1));x_max = max( coords_element{i}(:,1));
58  y_min = min( coords_element{i}(:,2));y_max = max( coords_element{i}(:,2));
59  BBox(i,:)=[x_min x_max y_min y_max];
60 
61  elem_area(i) = polyarea(coords_element{i}(:,1),coords_element{i}(:,2));
62  max_kb{i} = zeros(nedge(i),1);
63  for j = 1:nedge(i)
64  if j<nedge(i)
65  v1 = coords_element{i}(j,:); v2 = coords_element{i}(j+1,:);
66  ch_j = j;
67  ch_j_1 = j +1;
68  else
69  v1 = coords_element{i}(j,:); v2 = coords_element{i}(1,:);
70  ch_j = j;
71  ch_j_1 = j +1;
72  end
73  for k = 1:nedge(i)
74  if k~=ch_j && k~=ch_j_1
75  v3 = coords_element{i}(k,:);
76  [x_tria,y_tria]=poly2cw([v1(1) v2(1) v3(1)],[v1(2) v2(2) v3(2)]);
77  [x1,y1] = polybool('intersection',coords_element{i}(end:-1:1,1),coords_element{i}(end:-1:1,2),x_tria,y_tria);
78  area = polyarea(x_tria,y_tria);
79  if 1-any(isnan(x1)) && abs(polyarea(x1,y1)- area)<1e-6
80  if area>max_kb{i}(j)
81  max_kb{i}(j) = area;
82  end
83  end
84  end
85  end
86 
87  end
88 
89 end
90 
91 id_el = ones(ne,1);
92 
93 region=struct('nedges', nedge',...
94  'BBox',BBox,...
95  'ne',length(Element),...
96  'coord',coord,...
97  'id',id_el);
98 region.coords_element = coords_element;
99 region.connectivity = Element;
100 region.area = elem_area;
101 region.max_kb = max_kb;
102 
103 
104 
105 %------------------------------------------------- GENERATE RANDOM POINTSET
106 function P = PolyMshr_RndPtSet(NElem,Domain)
107 P=zeros(NElem,2); BdBox=Domain('BdBox'); Ctr=0;
108 while Ctr<NElem
109  Y(:,1) = (BdBox(2)-BdBox(1))*rand(NElem,1)+BdBox(1);
110  Y(:,2) = (BdBox(4)-BdBox(3))*rand(NElem,1)+BdBox(3);
111  d = Domain('Dist',Y);
112  I = find(d(:,end)<0); %Index of seeds inside the domain
113  NumAdded = min(NElem-Ctr,length(I)); %Number of seeds that can be added
114  P(Ctr+1:Ctr+NumAdded,:) = Y(I(1:NumAdded),:);
115  Ctr = Ctr+NumAdded;
116 end
117 %------------------------------------------------------------- FIXED POINTS
118 function [P,R_P] = PolyMshr_FixedPoints(P,R_P,PFix)
119 PP = [P;R_P];
120 for i = 1:size(PFix,1)
121  [B,I] = sort(sqrt((PP(:,1)-PFix(i,1)).^2+(PP(:,2)-PFix(i,2)).^2));
122  for j = 2:4
123  n = PP(I(j),:) - PFix(i,:); n = n/norm(n);
124  PP(I(j),:) = PP(I(j),:)-n*(B(j)-B(1));
125  end
126 end
127 P = PP(1:size(P,1),:); R_P = PP(1+size(P,1):end,:);
128 %--------------------------------------------------------- REFLECT POINTSET
129 function R_P = PolyMshr_Rflct(P,NElem,Domain,Alpha)
130 eps=1e-8; eta=0.9;
131 d = Domain('Dist',P);
132 NBdrySegs = size(d,2)-1; %Number of constituent bdry segments
133 n1 = (Domain('Dist',P+repmat([eps,0],NElem,1))-d)/eps;
134 n2 = (Domain('Dist',P+repmat([0,eps],NElem,1))-d)/eps;
135 I = abs(d(:,1:NBdrySegs))<Alpha; %Logical index of seeds near the bdry
136 P1 = repmat(P(:,1),1,NBdrySegs); %[NElem x NBdrySegs] extension of P(:,1)
137 P2 = repmat(P(:,2),1,NBdrySegs); %[NElem x NBdrySegs] extension of P(:,2)
138 R_P(:,1) = P1(I)-2*n1(I).*d(I);
139 R_P(:,2) = P2(I)-2*n2(I).*d(I);
140 d_R_P = Domain('Dist',R_P);
141 J = abs(d_R_P(:,end))>=eta*abs(d(I)) & d_R_P(:,end)>0;
142 R_P=R_P(J,:); R_P=unique(R_P,'rows');
143 %---------------------------------------------- COMPUTE CENTROID OF POLYGON
144 function [Pc,A] = PolyMshr_CntrdPly(Element,Node,NElem)
145 Pc=zeros(NElem,2); A=zeros(NElem,1);
146 for el = 1:NElem
147  vx=Node(Element{el},1); vy=Node(Element{el},2); nv=length(Element{el});
148  vxS=vx([2:nv 1]); vyS=vy([2:nv 1]); %Shifted vertices
149  temp = vx.*vyS - vy.*vxS;
150  A(el) = 0.5*sum(temp);
151  Pc(el,:) = 1/(6*A(el,1))*[sum((vx+vxS).*temp),sum((vy+vyS).*temp)];
152 end
153 %------------------------------------------------------- EXTRACT MESH NODES
154 function [Node,Element] = PolyMshr_ExtrNds(NElem,Node0,Element0)
155 map = unique([Element0{1:NElem}]);
156 cNode = 1:size(Node0,1);
157 cNode(setdiff(cNode,map)) = max(map);
158 [Node,Element] = PolyMshr_RbldLists(Node0,Element0(1:NElem),cNode);
159 %----------------------------------------------------- COLLAPSE SMALL EDGES
160 function [Node0,Element0] = PolyMshr_CllpsEdgs(Node0,Element0,Tol)
161 while(true)
162  cEdge = [];
163  for el=1:size(Element0,1)
164  if size(Element0{el},2)<4, continue; end; %Cannot collapse triangles
165  vx=Node0(Element0{el},1); vy=Node0(Element0{el},2); nv=length(vx);
166  beta = atan2(vy-sum(vy)/nv, vx-sum(vx)/nv);
167  beta = mod(beta([2:end 1]) -beta,2*pi);
168  betaIdeal = 2*pi/size(Element0{el},2);
169  Edge = [Element0{el}',Element0{el}([2:end 1])'];
170  cEdge = [cEdge; Edge(beta<Tol*betaIdeal,:)];
171  end
172  if (size(cEdge,1)==0), break; end
173  cEdge = unique(sort(cEdge,2),'rows');
174  cNode = 1:size(Node0,1);
175  for i=1:size(cEdge,1)
176  cNode(cEdge(i,2)) = cNode(cEdge(i,1));
177  end
178  [Node0,Element0] = PolyMshr_RbldLists(Node0,Element0,cNode);
179 end
180 %--------------------------------------------------------- RESEQUENSE NODES
181 function [Node,Element] = PolyMshr_RsqsNds(Node0,Element0)
182 NNode0=size(Node0,1); NElem0=size(Element0,1);
183 ElemLnght=cellfun(@length,Element0); nn=sum(ElemLnght.^2);
184 i=zeros(nn,1); j=zeros(nn,1); s=zeros(nn,1); index=0;
185 for el = 1:NElem0
186  eNode=Element0{el}; ElemSet=index+1:index+ElemLnght(el)^2;
187  i(ElemSet) = kron(eNode,ones(ElemLnght(el),1))';
188  j(ElemSet) = kron(eNode,ones(1,ElemLnght(el)))';
189  s(ElemSet) = 1;
190  index = index+ElemLnght(el)^2;
191 end
192 K = sparse(i,j,s,NNode0, NNode0);
193 p = symrcm(K);
194 cNode(p(1:NNode0))=1:NNode0;
195 [Node,Element] = PolyMshr_RbldLists(Node0,Element0,cNode);
196 %------------------------------------------------------------ REBUILD LISTS
197 function [Node,Element] = PolyMshr_RbldLists(Node0,Element0,cNode)
198 Element = cell(size(Element0,1),1);
199 [foo,ix,jx] = unique(cNode);
200 if ~isequal(size(jx),size(cNode)), jx=jx'; end % +R2013a compatibility fix
201 if size(Node0,1)>length(ix), ix(end)=max(cNode); end;
202 Node = Node0(ix,:);
203 for el=1:size(Element0,1)
204  Element{el} = unique(jx(Element0{el}));
205  vx=Node(Element{el},1); vy=Node(Element{el},2); nv=length(vx);
206  [foo,iix] = sort(atan2(vy-sum(vy)/nv,vx-sum(vx)/nv));
207  Element{el} = Element{el}(iix);
208 end
209 %---------------------------------------------------------------- PLOT MESH
210 function PolyMshr_PlotMsh(Node,Element,NElem,Supp,Load)
211 clf; axis equal; axis off; hold on;
212 Element = Element(1:NElem)'; %Only plot the first block
213 MaxNVer = max(cellfun(@numel,Element)); %Max. num. of vertices in mesh
214 PadWNaN = @(E) [E NaN(1,MaxNVer-numel(E))]; %Pad cells with NaN
215 ElemMat = cellfun(PadWNaN,Element,'UniformOutput',false);
216 ElemMat = vertcat(ElemMat{:}); %Create padded element matrix
217 patch('Faces',ElemMat,'Vertices',Node,'FaceColor','w'); pause(1e-6)
218 if exist('Supp','var')&&~isempty(Supp) %Plot Supp BC if specified
219  plot(Node(Supp(:,1),1),Node(Supp(:,1),2),'b>','MarkerSize',8);
220 end
221 if exist('Load','var')&&~isempty(Load) %Plot Load BC if specified
222  plot(Node(Load(:,1),1),Node(Load(:,1),2),'m^','MarkerSize',8);
223 end
224 %-------------------------------------------------------------------------%
225 %------------------------ PolyMesher - History ---------------------------%
226 % version: 1.1 (Aug13)
227 %
228 % history: Created: 8-Jan-12 Anderson Pereira & Cameron Talischi
229 % Supervised by: Ivan Menezes & Glaucio Paulino
230 %
231 % Modified: 6-Jun-13 Anderson Pereira
232 % Created a new function called "PolyMshr_FixedPoints" that
233 % allows to specify the exact location of vertices. For more
234 % information see Appendix A of Ref2.
235 %
236 % Modified: 14-Aug-13 Tomas Zegard and Sundararajan Natarajan
237 % Fixed the changed behaviour of the unique function in
238 % Matlab 2013a
239 %-------------------------------------------------------------------------%
function PolyMshr_ExtrNds(in NElem, in Node0, in Element0)
function PolyMshr_RndPtSet(in NElem, in Domain)
function PolyMshr_FixedPoints(in P, in R_P, in PFix)
function PolyMshr_RbldLists(in Node0, in Element0, in cNode)
function PolyMshr_Rflct(in P, in NElem, in Domain, in Alpha)
function PolyMesher(in Domain, in NElem, in MaxIter, in P)
function PolyMshr_RsqsNds(in Node0, in Element0)
function PolyMshr_CllpsEdgs(in Node0, in Element0, in Tol)
function PolyMshr_CntrdPly(in Element, in Node, in NElem)