0001 function [mapping failed] = mk_c2f_circ_mapping( mdl, xyzr );
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023 if isstr(mdl) && strcmp(mdl,'UNIT_TEST'); do_unit_test; return; end
0024
0025 failed = false;
0026
0027 c_obj = cache_obj(mdl, xyzr);
0028
0029 mapping = eidors_obj('get-cache', c_obj, 'circle_mapping');
0030 failed = eidors_obj('get-cache', c_obj, 'failed_circle_mapping');
0031 if ~isempty(mapping)
0032 eidors_msg('mk_c2f_circ_mapping: using cached value', 3);
0033 else
0034
0035 mdl = fix_model(mdl);
0036 switch size(xyzr,1)
0037 case 3; mapping = contained_elems_2d( mdl, xyzr );
0038 case 4; [mapping failed] = contained_elems_3d( mdl, xyzr );
0039 otherwise; error('size of xyzr incorrect');
0040 end
0041
0042 eidors_obj('set-cache', c_obj, 'circle_mapping', mapping);
0043 eidors_obj('set-cache', c_obj, 'failed_circle_mapping', failed);
0044 eidors_msg('mk_coarse_fine_mapping: setting cached value', 3);
0045 end
0046
0047
0048 function c_obj = cache_obj(mdl, xyzr)
0049 c_obj = {mdl.nodes, mdl.elems, xyzr};
0050
0051
0052 function mapping = contained_elems_2d( mdl, xyr );
0053
0054 mapping = contained_elems_2d_old( mdl, xyr );
0055
0056 function mapping = contained_elems_2d_new( mdl, xyr );
0057
0058 Nc = size(xyr, 2);
0059 too_far = elems_too_far( mdl, xyr );
0060
0061 mapping = sparse( num_elems(mdl) , Nc );
0062 for i=1:Nc
0063 mapping(:,i) = circ_in_elem_2d(mdl, find( ~too_far(:,i)), ...
0064 xyr(1,i), xyr(2,i), xyr(3,i));
0065 end
0066
0067
0068 function mapping = circ_in_elem_2d( mdl, look, xc, yc, rc);
0069 Nt = elem_dim(mdl) + 1;
0070 pirc2 = pi*rc^2;
0071
0072 mapping = sparse(num_elems(mdl),1);
0073
0074 els = mdl.elems(look,:);
0075 ndx = reshape(mdl.nodes(els,1) - xc, size(els));
0076 ndy = reshape(mdl.nodes(els,2) - yc, size(els));
0077 n_in = (ndx.^2 + ndy.^2) < rc^2;
0078
0079 all_n_in = sum(n_in,2) == Nt;
0080 mapping(look(all_n_in)) = 1;
0081 look(all_n_in)= []; n_in(all_n_in,:)= [];
0082
0083 f_in = zeros( length(look), Nt);
0084 k=1; for i= look(:)';
0085 faces = mdl.elem2face(i,:);
0086 out =~mdl.inner_normal(i,:);
0087 f_norm= mdl.normals( faces, :);
0088 f_norm(out,:) = -f_norm(out,:);
0089
0090 f_ctr = mdl.face_centre( faces,:);
0091 v_ctr = repmat([xc,yc],Nt,1) - f_ctr;
0092 v_ctr = sum(v_ctr .* f_norm,2)/rc;
0093 f_in(k,:) = v_ctr';
0094 k=k+1;end
0095
0096
0097 any_s_out= any(f_in<-1,2);
0098 look(any_s_out)= [];
0099 n_in(any_s_out,:) = [];
0100 f_in(any_s_out,:) = [];
0101
0102
0103 all_s_in = sum(f_in>1,2) == Nt;
0104 mapping(look(all_s_in)) = pirc2 / ...
0105 mdl.elem_volume(look(all_s_in));
0106 look(all_s_in)= [];
0107 n_in(all_s_in) = [];
0108 f_in(all_s_in) = [];
0109
0110
0111
0112 fin1 = f_in<1;
0113 a_out = zeros(size(fin1));
0114 a_out(fin1) = acos(f_in(fin1));
0115 a_out(fin1) = (a_out(fin1) - cos(a_out(fin1)).*sin(a_out(fin1)))/pi;
0116
0117
0118
0119
0120 mapping(look) = pirc2 / mdl.elem_volume(look);
0121
0122
0123 k=1; for i= look(:)';
0124 vol = pi*rc^2 / mdl.elem_volume(i);
0125 switch sum(n_in(k,:))
0126 case 0;
0127
0128 case 1;
0129 nd = mdl.elems(k, n_in(k,:));
0130 vol = vol + pi_slice(p1,p2,[xc,yc],mdl.nodes(nd,:),rc);
0131
0132 case 2;
0133 nd = mdl.elems(k, n_in(k,:));
0134 vol = vol ...
0135 + pi_slice(p1,p2,[xc,yc],mdl.nodes(nd(1),:),rc) ...
0136 + pi_slice(p1,p2,[xc,yc],mdl.nodes(nd(2),:),rc);
0137
0138 otherwise; error('cant get here');
0139 end
0140 k=k+1; end
0141
0142
0143
0144 function a = pi_slice(p1,p2,c,p,r)
0145 a_p12 = 0.5*abs(det([1,p1;1,p2;1,p]));
0146
0147 a_c12 = 0.5*abs(det([1,p1;1,p2;1,c]));
0148 np1c = p1-c; np1c = np1c / norm(np1c);
0149 np2c = p2-c; np2c = np2c / norm(np2c);
0150 ang = acos( dot(np1c,np2c) );
0151 area = ang*r^2/2 - a_c12 + a_p12;
0152
0153
0154 function mapping = contained_elems_2d_old( mdl, xyr );
0155 Ne = size(mdl.elems,1);
0156 Nc = size(xyr, 2);
0157
0158 mapping = sparse( Ne, Nc );
0159
0160
0161 n_interp = 7-size(mdl.nodes,2);
0162 m_pts = interp_mesh( mdl, n_interp);
0163 for i=1:Nc
0164 xc = m_pts(:,1,:) - xyr(1,i);
0165 yc = m_pts(:,2,:) - xyr(2,i);
0166 inr= xc.^2 + yc.^2 < xyr(3,i)^2;
0167 frac= mean(inr,3);
0168 mapping(:,i) = frac;
0169 end
0170
0171
0172
0173
0174 function too_far = elems_too_far( mdl, xyr );
0175 Ne = num_elems(mdl);
0176 Nc = size(xyr, 2);
0177 Nt = elem_dim(mdl) + 1;
0178 if 0
0179 nodes = repmat(mdl.nodes,[1,1,Nc]);
0180 targets = repmat(xyr(1:mdl_dim(mdl),:),[1,1,num_nodes(mdl)]);
0181 targets = shiftdim(targets,2);
0182 dist = nodes - targets;
0183 dist = sqrt(sum(dist.^2,2));
0184 node_target_dist = squeeze(dist);
0185 furthest_elem_node_dist = node_target_dist(mdl.elems,:);
0186 furthest_elem_node_dist = reshape(furthest_elem_node_dist,Ne,Nt,Nc);
0187 [furthest_elem_node_dist, furthest_elem_node]= max(furthest_elem_node_dist,[],2);
0188 furthest_elem_node_dist = squeeze(furthest_elem_node_dist);
0189 furthest_elem_node = squeeze(furthest_elem_node);
0190 max_edge_len = repmat(mdl.max_edge_len,1,Nc);
0191 radius = ones(Ne,1)*xyr(Nt,:);
0192 too_far = (furthest_elem_node_dist - max_edge_len) > radius;
0193 else
0194 too_far = false(Ne,Nc);
0195 for i = 1:Nc
0196 targets = repmat(xyr(1:mdl_dim(mdl),i),[1,num_nodes(mdl)])';
0197 dist = mdl.nodes - targets;
0198 dist = sqrt(sum(dist.^2,2));
0199 furthest_elem_node_dist =max(dist(mdl.elems),[],2);
0200 too_far(:,i) = (furthest_elem_node_dist - mdl.max_edge_len) > xyr(Nt,i);
0201 end
0202 end
0203
0204
0205
0206
0207 function [mapping failed] = contained_elems_3d( mdl, xyr );
0208 Ne = size(mdl.elems,1);
0209 Nc = size(xyr, 2);
0210 failed(1:Nc) = false;
0211
0212 mapping = sparse( Ne, Nc );
0213 if 0
0214
0215 n_interp = 4;
0216 m_pts = interp_mesh( mdl, n_interp);
0217 for i=1:Nc
0218 mapping(:,i) = contained_elem_pts(m_pts, xyr(:,i));
0219 end
0220 else
0221
0222
0223
0224
0225
0226 too_far = elems_too_far( mdl, xyr );
0227
0228 tmp = eidors_obj('fwd_model','tmp','nodes',mdl.nodes,'elems',mdl.elems);
0229
0230 n_interp_min = 4;
0231 n_interp_max = 10;
0232 for i=1:Nc
0233 good = ~too_far(:,i);
0234 if ~any(good), continue, end
0235 tmp.elems = mdl.elems(good,:);
0236 n_interp = n_interp_min-1;
0237 log_level = eidors_msg('log_level',1);
0238 while(sum(mapping(good,i))==0 && n_interp < n_interp_max-1)
0239 n_interp = n_interp+1;
0240 m_pts = interp_mesh( tmp, n_interp);
0241 mapping(good,i) = contained_elem_pts(m_pts, xyr(:,i));
0242 end
0243 eidors_msg('log_level', log_level);
0244 if (sum(mapping(good,i)) == 0)
0245 failed(i) = true;
0246 eidors_msg(['mk_c2f_circ_mapping: Interpolation failed for point ' num2str(i)]);
0247 end
0248 end
0249 end
0250
0251
0252 function frac= contained_elem_pts(m_pts, xyr);
0253
0254
0255
0256
0257
0258
0259
0260 inr = (m_pts(:,1,:) - xyr(1)).^2 + ...
0261 (m_pts(:,2,:) - xyr(2)).^2 + ...
0262 (m_pts(:,3,:) - xyr(3)).^2;
0263 inpts = inr < xyr(4)^2;
0264
0265
0266
0267 frac= mean( int8( inpts ) ,3);
0268 if sum(inpts(:))==0
0269
0270 eidors_msg(['mk_c2f_circ_mapping: Interpolation failed: increase ', ...
0271 'fwd_model.interp_mesh.n_interp']);
0272 end
0273
0274 function do_unit_test
0275
0276 imdl = mk_common_model('a2c2',16); fmdl=imdl.fwd_model;
0277 xyc = [0,0.27,0.18;0,-0.1,0.03;0,0.1,0.2;0.1,0.37,0.1]';
0278 th=linspace(0,2*pi,20)';
0279 xx=[0*th+1]*xyc(1,:)+sin(th)*xyc(3,:);
0280 yy=[0*th+1]*xyc(2,:)+cos(th)*xyc(3,:);
0281 show_fem(fmdl,[0,0,1]); set(line(xx,yy),'LineWidth',2);
0282
0283 c2f= mk_c2f_circ_mapping( fmdl, [0;0;0.1] );
0284 t1= all( abs(c2f(1:4)-0.2857)<.001 ) & all( c2f(5:end)==0 );
0285 unit_test_cmp('2D ex 1:',t1,1);
0286
0287 c2f= mk_c2f_circ_mapping( fmdl, [.0;.05;0.03]);
0288 t2= abs( c2f(1) - 0.1429) < .001 & all( c2f(2:end)==0 );
0289 unit_test_cmp('2D ex 2:',t2,1);
0290
0291
0292 imdl = mk_common_model('a3cr',16); fmdl=imdl.fwd_model;
0293 c2f= mk_c2f_circ_mapping( fmdl, [0;0;0.1]);
0294 t3= all( abs(c2f(1:4)-0.1714)<.001 ) & all( c2f(5:64)==0 );
0295 unit_test_cmp('3D ex 1:',t2,1);
0296
0297
0298 imdl = mk_common_model('a3cr',16); fmdl=imdl.fwd_model;
0299 c2f= mk_c2f_circ_mapping( fmdl, [0;0;0;0.1]);
0300 unit_test_cmp('3D ex 2a:',c2f(193:196),.0571,.001);
0301 unit_test_cmp('3D ex 2b:',c2f(1:64),0);
0302
0303
0304 imdl = mk_common_model('a3cr',16); fmdl=imdl.fwd_model;
0305 c2f= mk_c2f_circ_mapping( fmdl, [0 0;0 0;0 0;0.1 0.2]);
0306 unit_test_cmp('3D ex 3a:',c2f(193:196),.0571,.001);
0307 unit_test_cmp('3D ex 3b:',c2f(1:64),0);