| 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
|
|---|