2 %> @author Ilario Mazzieri
3 %> @brief Modified version of the original
PolyMesher main file - version 1.1.
5 %> The original version is taken from http:
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 %
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 %>-------------------------------------------------------------------------%
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));
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);
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;
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
44 elem_area = zeros(ne,1);
48 coords_element = cell(1,ne);
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];
61 elem_area(i) = polyarea(coords_element{i}(:,1),coords_element{i}(:,2));
62 max_kb{i} = zeros(nedge(i),1);
65 v1 = coords_element{i}(j,:); v2 = coords_element{i}(j+1,:);
69 v1 = coords_element{i}(j,:); v2 = coords_element{i}(1,:);
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
93 region=struct('nedges
', nedge',...
95 'ne',length(Element),...
98 region.coords_element = coords_element;
99 region.connectivity = Element;
100 region.area = elem_area;
101 region.max_kb = max_kb;
105 %------------------------------------------------- GENERATE RANDOM POINTSET
107 P=zeros(NElem,2); BdBox=Domain(
'BdBox'); Ctr=0;
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),:);
117 %------------------------------------------------------------- FIXED POINTS
120 for i = 1:size(PFix,1)
121 [B,I] = sort(sqrt((PP(:,1)-PFix(i,1)).^2+(PP(:,2)-PFix(i,2)).^2));
123 n = PP(I(j),:) - PFix(i,:); n = n/norm(n);
124 PP(I(j),:) = PP(I(j),:)-n*(B(j)-B(1));
127 P = PP(1:size(P,1),:); R_P = PP(1+size(P,1):end,:);
128 %--------------------------------------------------------- REFLECT POINTSET
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
145 Pc=zeros(NElem,2); A=zeros(NElem,1);
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)];
153 %------------------------------------------------------- EXTRACT MESH NODES
155 map = unique([Element0{1:NElem}]);
156 cNode = 1:size(Node0,1);
157 cNode(setdiff(cNode,map)) = max(map);
159 %----------------------------------------------------- COLLAPSE SMALL EDGES
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,:)];
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));
180 %--------------------------------------------------------- RESEQUENSE NODES
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;
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)))';
190 index = index+ElemLnght(el)^2;
192 K = sparse(i,j,s,NNode0, NNode0);
194 cNode(p(1:NNode0))=1:NNode0;
196 %------------------------------------------------------------ REBUILD LISTS
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;
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);
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);
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);
224 %-------------------------------------------------------------------------%
225 %------------------------
PolyMesher - History ---------------------------%
226 % version: 1.1 (Aug13)
228 % history: Created: 8-Jan-12 Anderson Pereira & Cameron Talischi
229 % Supervised by: Ivan Menezes & Glaucio Paulino
231 % Modified: 6-Jun-13 Anderson Pereira
233 % allows to specify the exact location of vertices. For more
234 % information see Appendix A of Ref2.
236 % Modified: 14-Aug-13 Tomas Zegard and Sundararajan Natarajan
237 % Fixed the changed behaviour of the unique function in
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)