1 | %
|
---|
2 | % function to create the adjacency matrix from the connectivity table.
|
---|
3 | %
|
---|
4 | % [adj_mat,vlist,vwgt]=adjacency_matrix(elem_con,xyz)
|
---|
5 | %
|
---|
6 | % where the required input is:
|
---|
7 | % elem_con (double [ne x mvpe], element connectivity table)
|
---|
8 | % xyz (double [nv x 3 ], vertex coordinates)
|
---|
9 | %
|
---|
10 | % the required output is:
|
---|
11 | % adj_mat (double [sparse nv x nv], vertex adjacency matrix)
|
---|
12 | % vlist (double [nv], vertex labels)
|
---|
13 | % vwgt (double [nv], vertex weights)
|
---|
14 | %
|
---|
15 | function [adj_mat,vlist,vwgt]=adjacency_matrix(elem_con,xyz)
|
---|
16 |
|
---|
17 | if ~nargin
|
---|
18 | help adjacency_matrix
|
---|
19 | return
|
---|
20 | end
|
---|
21 |
|
---|
22 | % can modify local elem_con, since it's not being returned
|
---|
23 |
|
---|
24 | elem_con(~isfinite(elem_con))=0;
|
---|
25 |
|
---|
26 | %% create unique sorted vertex list, eliminating NaN, Inf, and zero
|
---|
27 |
|
---|
28 | disp('Creating unique sorted vertex list.');
|
---|
29 | vlist=unique(nonzeros(elem_con));
|
---|
30 | fprintf(' Found %d vertices numbered from %d to %d.\n',...
|
---|
31 | length(vlist),vlist(1),vlist(end));
|
---|
32 |
|
---|
33 | %% create edge list and vertex weights
|
---|
34 |
|
---|
35 | disp('Creating edge list and vertex weights.');
|
---|
36 | nedge=0;
|
---|
37 | elist=zeros(numel(elem_con),2);
|
---|
38 | asum= 0.;
|
---|
39 | amin= Inf;
|
---|
40 | amax=-Inf;
|
---|
41 | vsum= 0.;
|
---|
42 | vmin= Inf;
|
---|
43 | vmax=-Inf;
|
---|
44 | vwgt =zeros(size(vlist));
|
---|
45 |
|
---|
46 | % loop over elements
|
---|
47 |
|
---|
48 | fprintf(' Processing %d elements with a maximum of %d vertices.\n',...
|
---|
49 | size(elem_con,1),size(elem_con,2));
|
---|
50 | %hwbar=waitbar(0);
|
---|
51 | for i=1:size(elem_con,1)
|
---|
52 | elem=nonzeros(elem_con(i,:));
|
---|
53 |
|
---|
54 | % replace vertex numbers by indices (if necessary)
|
---|
55 |
|
---|
56 | if (vlist(1) ~= 1) || (vlist(end) ~= length(vlist))
|
---|
57 | elem=bin_search(elem,vlist);
|
---|
58 | end
|
---|
59 |
|
---|
60 | % accumulate edge list for each element type
|
---|
61 |
|
---|
62 | switch length(elem)
|
---|
63 |
|
---|
64 | % tria
|
---|
65 |
|
---|
66 | case 3
|
---|
67 | elist(nedge+1,1)=elem(1);
|
---|
68 | elist(nedge+1,2)=elem(2);
|
---|
69 | elist(nedge+2,1)=elem(2);
|
---|
70 | elist(nedge+2,2)=elem(3);
|
---|
71 | elist(nedge+3,1)=elem(3);
|
---|
72 | elist(nedge+3,2)=elem(1);
|
---|
73 | nedge=nedge+3;
|
---|
74 |
|
---|
75 | if exist('xyz','var')
|
---|
76 | area=mag(cross(xyz(elem(2),:)-xyz(elem(1),:),...
|
---|
77 | xyz(elem(3),:)-xyz(elem(1),:)))/2;
|
---|
78 | asum=asum+area;
|
---|
79 | if (area < amin)
|
---|
80 | amin=area;
|
---|
81 | end
|
---|
82 | if (area > amax)
|
---|
83 | amax=area;
|
---|
84 | end
|
---|
85 | for j=1:3
|
---|
86 | vwgt(elem(j))=vwgt(elem(j))+area/3;
|
---|
87 | end
|
---|
88 | end
|
---|
89 |
|
---|
90 | % penta
|
---|
91 |
|
---|
92 | case 6
|
---|
93 | elist(nedge+1,1)=elem(1);
|
---|
94 | elist(nedge+1,2)=elem(2);
|
---|
95 | elist(nedge+2,1)=elem(2);
|
---|
96 | elist(nedge+2,2)=elem(3);
|
---|
97 | elist(nedge+3,1)=elem(3);
|
---|
98 | elist(nedge+3,2)=elem(1);
|
---|
99 | elist(nedge+4,1)=elem(1);
|
---|
100 | elist(nedge+4,2)=elem(4);
|
---|
101 | elist(nedge+5,1)=elem(2);
|
---|
102 | elist(nedge+5,2)=elem(5);
|
---|
103 | elist(nedge+6,1)=elem(3);
|
---|
104 | elist(nedge+6,2)=elem(6);
|
---|
105 | elist(nedge+7,1)=elem(7);
|
---|
106 | elist(nedge+7,2)=elem(8);
|
---|
107 | elist(nedge+8,1)=elem(8);
|
---|
108 | elist(nedge+8,2)=elem(9);
|
---|
109 | elist(nedge+9,1)=elem(9);
|
---|
110 | elist(nedge+9,2)=elem(7);
|
---|
111 | nedge=nedge+9;
|
---|
112 |
|
---|
113 | if exist('xyz','var')
|
---|
114 | vol =mag(cross(xyz(elem(2),:)-xyz(elem(1),:),...
|
---|
115 | xyz(elem(3),:)-xyz(elem(1),:)))/2*...
|
---|
116 | mag(xyz(elem(4),:)-xyz(elem(1),:));
|
---|
117 | vsum=vsum+vol;
|
---|
118 | if (vol < vmin)
|
---|
119 | vmin=vol;
|
---|
120 | end
|
---|
121 | if (vol > vmax)
|
---|
122 | vmax=vol;
|
---|
123 | end
|
---|
124 | for j=1:6
|
---|
125 | vwgt(elem(j))=vwgt(elem(j))+vol/6;
|
---|
126 | end
|
---|
127 | end
|
---|
128 |
|
---|
129 | otherwise
|
---|
130 | error(['Unrecognized element of length' length(elem) '.']);
|
---|
131 | end
|
---|
132 | if (i/100 == floor(i/100))
|
---|
133 | fprintf(' %d elements processed.\n',i);
|
---|
134 | %waitbar(i/size(elem_con,1),hwbar,sprintf('%d elements processed.',i));
|
---|
135 | end
|
---|
136 | end
|
---|
137 | fprintf(' %d total elements processed.\n\n',i);
|
---|
138 | %waitbar(1,hwbar,sprintf('%d total elements processed.',i));
|
---|
139 | %close(hwbar)
|
---|
140 |
|
---|
141 | if (asum > 0)
|
---|
142 | fprintf('Total area=%f; min area=%f, max area=%f, ratio=%f.\n',...
|
---|
143 | asum,amin,amax,amax/amin);
|
---|
144 | end
|
---|
145 | if (vsum > 0)
|
---|
146 | fprintf('Total volume=%f; min volume=%f, max volume=%f, ratio=%f.\n',...
|
---|
147 | vsum,vmin,vmax,vmax/vmin);
|
---|
148 | end
|
---|
149 | fprintf('Total weight=%f; min weight=%f, max weight=%f, ratio=%f.\n',...
|
---|
150 | sum(vwgt),min(vwgt),max(vwgt),max(vwgt)/min(vwgt));
|
---|
151 |
|
---|
152 | elist=elist(1:nedge,:);
|
---|
153 |
|
---|
154 | %% replace vertex numbers by indices (if necessary)
|
---|
155 |
|
---|
156 | % if (vlist(1) ~= 1) || (vlist(end) ~= length(vlist))
|
---|
157 | % elist=bin_search(elist,vlist);
|
---|
158 | % end
|
---|
159 |
|
---|
160 | %% create adjacency matrix and make symmetric
|
---|
161 |
|
---|
162 | adj_mat=sparse(elist(:,1),elist(:,2),1,length(vlist),length(vlist));
|
---|
163 | adj_mat=double(adj_mat | adj_mat');
|
---|
164 |
|
---|
165 | end
|
---|
166 |
|
---|
167 | %
|
---|
168 | % function to perform a recursive binary search for a matrix of values
|
---|
169 | % in an ordered vector (loop separately outside of recursion for
|
---|
170 | % efficiency purposes)
|
---|
171 | %
|
---|
172 | % function [ind]=bin_search(val,vect)
|
---|
173 | %
|
---|
174 | function [ind]=bin_search(val,vect)
|
---|
175 |
|
---|
176 | ind=zeros(size(val));
|
---|
177 |
|
---|
178 | for i=1:numel(val)
|
---|
179 | ind(i)=bin_search_val(val(i),vect);
|
---|
180 | end
|
---|
181 |
|
---|
182 | end
|
---|
183 |
|
---|
184 | %
|
---|
185 | % function to perform a recursive binary search in an ordered vector,
|
---|
186 | % returning NaN if value does not exist (more efficient than find or
|
---|
187 | % ismember, which must use linear searches and/or sort)
|
---|
188 | %
|
---|
189 | % function [ind]=bin_search_val(val,vect)
|
---|
190 | %
|
---|
191 | function [ind]=bin_search_val(val,vect)
|
---|
192 |
|
---|
193 | imid=floor((1+length(vect))/2);
|
---|
194 |
|
---|
195 | if (val == vect(imid))
|
---|
196 | ind=imid;
|
---|
197 | elseif (val < vect(imid)) && (imid > 1)
|
---|
198 | ind= bin_search(val,vect(1:imid-1));
|
---|
199 | elseif (val > vect(imid)) && (imid < length(vect))
|
---|
200 | ind=imid+bin_search(val,vect(imid+1:length(vect)));
|
---|
201 | else
|
---|
202 | ind=NaN;
|
---|
203 | end
|
---|
204 |
|
---|
205 | end
|
---|
206 |
|
---|
207 | %
|
---|
208 | % function to calculate the magnitude of a vector
|
---|
209 | %
|
---|
210 | % function [vmag]=mag(vect)
|
---|
211 | %
|
---|
212 | function [vmag]=mag(vect)
|
---|
213 |
|
---|
214 | vmag=sqrt(dot(vect,vect));
|
---|
215 |
|
---|
216 | end
|
---|