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
0024
0025
0026 if ischar(mdl) && strcmp(mdl,'UNIT_TEST'); do_unit_test; return; end
0027
0028 copt.cache_obj = cache_obj(mdl, xyzr);
0029 copt.fstr = 'mk_c2f_circ_mapping';
0030 [mapping, failed] = eidors_cache(@circ_mapping,{mdl,xyzr},copt);
0031
0032 function [mapping, failed] = circ_mapping(mdl,xyzr,copt)
0033
0034 failed = false;
0035 mdl = fix_model(mdl);
0036 switch size(xyzr,1)
0037 case 3;
0038 mapping = contained_elems_2d( mdl, xyzr );
0039 if mdl_dim(mdl) == 2;
0040 correctmap = pi*xyzr(end,:).^2;
0041 else
0042
0043 correctmap = (get_elem_volume(mdl)'*mapping);
0044 end
0045 case 4;
0046 [mapping failed] = contained_elems_3d( mdl, xyzr );
0047 correctmap = 4/3*pi*xyzr(end,:).^3;
0048 otherwise; error('size of xyzr incorrect');
0049 end
0050
0051
0052 vol = get_elem_volume(mdl,-2)';
0053
0054
0055
0056 mapping = bsxfun(@times, mapping, ...
0057 correctmap./(vol*mapping));
0058
0059
0060 function c_obj = cache_obj(mdl, xyzr)
0061 c_obj = {mdl.nodes, mdl.elems, xyzr};
0062
0063
0064 function mapping = contained_elems_2d( mdl, xyr );
0065
0066 mapping = contained_elems_2d_old( mdl, xyr );
0067
0068 function mapping = contained_elems_2d_new( mdl, xyr );
0069
0070 Nc = size(xyr, 2);
0071 too_far = elems_too_far( mdl, xyr );
0072
0073 mapping = sparse( num_elems(mdl) , Nc );
0074 for i=1:Nc
0075 mapping(:,i) = circ_in_elem_2d(mdl, find( ~too_far(:,i)), ...
0076 xyr(1,i), xyr(2,i), xyr(3,i));
0077 end
0078
0079
0080 function mapping = circ_in_elem_2d( mdl, look, xc, yc, rc);
0081 Nt = elem_dim(mdl) + 1;
0082 pirc2 = pi*rc^2;
0083
0084 mapping = sparse(num_elems(mdl),1);
0085
0086 els = mdl.elems(look,:);
0087 ndx = reshape(mdl.nodes(els,1) - xc, size(els));
0088 ndy = reshape(mdl.nodes(els,2) - yc, size(els));
0089 n_in = (ndx.^2 + ndy.^2) < rc^2;
0090
0091 all_n_in = sum(n_in,2) == Nt;
0092 mapping(look(all_n_in)) = 1;
0093 look(all_n_in)= []; n_in(all_n_in,:)= [];
0094
0095 f_in = zeros( length(look), Nt);
0096 k=1; for i= look(:)';
0097 faces = mdl.elem2face(i,:);
0098 out =~mdl.inner_normal(i,:);
0099 f_norm= mdl.normals( faces, :);
0100 f_norm(out,:) = -f_norm(out,:);
0101
0102 f_ctr = mdl.face_centre( faces,:);
0103 v_ctr = repmat([xc,yc],Nt,1) - f_ctr;
0104 v_ctr = sum(v_ctr .* f_norm,2)/rc;
0105 f_in(k,:) = v_ctr';
0106 k=k+1;end
0107
0108
0109 any_s_out= any(f_in<-1,2);
0110 look(any_s_out)= [];
0111 n_in(any_s_out,:) = [];
0112 f_in(any_s_out,:) = [];
0113
0114
0115 all_s_in = sum(f_in>1,2) == Nt;
0116 mapping(look(all_s_in)) = pirc2 / ...
0117 mdl.elem_volume(look(all_s_in));
0118 look(all_s_in)= [];
0119 n_in(all_s_in) = [];
0120 f_in(all_s_in) = [];
0121
0122
0123
0124 fin1 = f_in<1;
0125 a_out = zeros(size(fin1));
0126 a_out(fin1) = acos(f_in(fin1));
0127 a_out(fin1) = (a_out(fin1) - cos(a_out(fin1)).*sin(a_out(fin1)))/pi;
0128
0129
0130
0131
0132 mapping(look) = pirc2 / mdl.elem_volume(look);
0133
0134
0135 k=1; for i= look(:)';
0136 vol = pi*rc^2 / mdl.elem_volume(i);
0137 switch sum(n_in(k,:))
0138 case 0;
0139
0140 case 1;
0141 nd = mdl.elems(k, n_in(k,:));
0142 vol = vol + pi_slice(p1,p2,[xc,yc],mdl.nodes(nd,:),rc);
0143
0144 case 2;
0145 nd = mdl.elems(k, n_in(k,:));
0146 vol = vol ...
0147 + pi_slice(p1,p2,[xc,yc],mdl.nodes(nd(1),:),rc) ...
0148 + pi_slice(p1,p2,[xc,yc],mdl.nodes(nd(2),:),rc);
0149
0150 otherwise; error('cant get here');
0151 end
0152 k=k+1; end
0153
0154
0155
0156 function a = pi_slice(p1,p2,c,p,r)
0157 a_p12 = 0.5*abs(det([1,p1;1,p2;1,p]));
0158
0159 a_c12 = 0.5*abs(det([1,p1;1,p2;1,c]));
0160 np1c = p1-c; np1c = np1c / norm(np1c);
0161 np2c = p2-c; np2c = np2c / norm(np2c);
0162 ang = acos( dot(np1c,np2c) );
0163 area = ang*r^2/2 - a_c12 + a_p12;
0164
0165
0166 function mapping = contained_elems_2d_old( mdl, xyr );
0167 Ne = size(mdl.elems,1);
0168 Nc = size(xyr, 2);
0169
0170 mapping = sparse( Ne, Nc );
0171
0172
0173 n_interp = 7-size(mdl.nodes,2);
0174 m_pts = interp_mesh( mdl, n_interp);
0175 for i=1:Nc
0176 xc = m_pts(:,1,:) - xyr(1,i);
0177 yc = m_pts(:,2,:) - xyr(2,i);
0178 inr= xc.^2 + yc.^2 < xyr(3,i)^2;
0179 frac= mean(inr,3);
0180 mapping(:,i) = frac;
0181 end
0182
0183
0184
0185
0186 function too_far = elems_too_far( mdl, xyr );
0187 Ne = num_elems(mdl);
0188 Nc = size(xyr, 2);
0189 Nt = elem_dim(mdl) + 1;
0190 if 0
0191 nodes = repmat(mdl.nodes,[1,1,Nc]);
0192 targets = repmat(xyr(1:mdl_dim(mdl),:),[1,1,num_nodes(mdl)]);
0193 targets = shiftdim(targets,2);
0194 dist = nodes - targets;
0195 dist = sqrt(sum(dist.^2,2));
0196 node_target_dist = squeeze(dist);
0197 furthest_elem_node_dist = node_target_dist(mdl.elems,:);
0198 furthest_elem_node_dist = reshape(furthest_elem_node_dist,Ne,Nt,Nc);
0199 [furthest_elem_node_dist, furthest_elem_node]= max(furthest_elem_node_dist,[],2);
0200 furthest_elem_node_dist = squeeze(furthest_elem_node_dist);
0201 furthest_elem_node = squeeze(furthest_elem_node);
0202 max_edge_len = repmat(mdl.max_edge_len,1,Nc);
0203 radius = ones(Ne,1)*xyr(Nt,:);
0204 too_far = (furthest_elem_node_dist - max_edge_len) > radius;
0205 else
0206 too_far = false(Ne,Nc);
0207 progress_msg('mk_c2f_circ_mapping: prepare models',0,Nc);
0208 for i = 1:Nc
0209 progress_msg(i,Nc);
0210 targets = repmat(xyr(1:mdl_dim(mdl),i),[1,num_nodes(mdl)])';
0211 dist = mdl.nodes - targets;
0212 dist = sqrt(sum(dist.^2,2));
0213 furthest_elem_node_dist =max(dist(mdl.elems),[],2);
0214 too_far(:,i) = (furthest_elem_node_dist - mdl.max_edge_len) > xyr(Nt,i);
0215 end
0216 progress_msg(Inf);
0217 end
0218
0219
0220
0221
0222 function [mapping failed] = contained_elems_3d( mdl, xyr );
0223 Ne = size(mdl.elems,1);
0224 Nc = size(xyr, 2);
0225 failed(1:Nc) = false;
0226
0227 mapping = sparse( Ne, Nc );
0228
0229
0230
0231
0232
0233 too_far = elems_too_far( mdl, xyr );
0234
0235 tmp = eidors_obj('fwd_model','tmp','nodes',mdl.nodes,'elems',mdl.elems);
0236
0237 try
0238 n_interp_min = mdl.interp_mesh.n_points;
0239 catch
0240 n_interp_min = 4;
0241 end
0242 n_interp_max = 10;
0243
0244 if 0
0245
0246 n_interp = 4;
0247 m_pts = interp_mesh( mdl, n_interp);
0248 for i=1:Nc
0249 mapping(:,i) = contained_elem_pts(m_pts, xyr(:,i));
0250 end
0251 else
0252
0253 progress_msg('mk_c2f_circ_mapping: calculate mapping',0,Nc);
0254 for i=1:Nc
0255 progress_msg(i,Nc);
0256 good = ~too_far(:,i);
0257 if ~any(good);
0258 failed(i) = true;
0259 continue
0260 end
0261 tmp.elems = mdl.elems(good,:);
0262 n_interp = n_interp_min-1;
0263 log_level = eidors_msg('log_level',1);
0264 while(sum(mapping(good,i))==0 && n_interp < n_interp_max-1)
0265 n_interp = n_interp+1;
0266 m_pts = interp_mesh( tmp, n_interp);
0267 mapping(good,i) = contained_elem_pts(m_pts, xyr(:,i));
0268 end
0269 eidors_msg('log_level', log_level);
0270 if (sum(mapping(good,i)) == 0)
0271 failed(i) = true;
0272 eidors_msg(['mk_c2f_circ_mapping: Interpolation failed for point ' num2str(i)],3);
0273 end
0274 end
0275 progress_msg(sprintf( ...
0276 ': Outside=%d/%d', sum(failed),Nc),Inf);
0277 end
0278
0279
0280 function frac= contained_elem_pts(m_pts, xyr);
0281
0282
0283
0284
0285
0286
0287
0288 inr = (m_pts(:,1,:) - xyr(1)).^2 + ...
0289 (m_pts(:,2,:) - xyr(2)).^2 + ...
0290 (m_pts(:,3,:) - xyr(3)).^2;
0291 inpts = inr < xyr(4)^2;
0292
0293 frac= mean( inpts ,3);
0294 if sum(inpts(:))==0
0295
0296 eidors_msg(['mk_c2f_circ_mapping: Interpolation failed: increase ', ...
0297 'fwd_model.interp_mesh.n_interp']);
0298 end
0299
0300 function do_outside_test()
0301 fmdl= ng_mk_ellip_models([1,1.2,0.8,.1],[16,0.5],0.05);
0302 maxn = max(fmdl.nodes); minn = min(fmdl.nodes);
0303 lsx = linspace(minn(1),maxn(1),31);
0304 lsy = linspace(minn(2),maxn(2),21);
0305 [x,y] = meshgrid(lsx,lsy); zz = 0*x(:);
0306 xyzr= [x(:), y(:), zz+0.5, zz+0.1]';
0307 [map,fail] = mk_c2f_circ_mapping(fmdl,xyzr);
0308 unit_test_cmp('Outside#:',sum(fail),96);
0309 unit_test_cmp('Outside Fail:',fail, any(isnan(map),1));
0310
0311 function do_unit_test
0312 do_outside_test()
0313 fmdl = ng_mk_cyl_models([0,1,.1],[16,1],.03);
0314 vol = get_elem_volume(fmdl)';
0315 xyr = ones(3,1)*linspace(-.5,.5,7);
0316 rr = .1; VV = pi*rr^2; xyr(3,:) = rr;
0317 [c2f,fail] = mk_c2f_circ_mapping(fmdl,xyr);
0318 unit_test_cmp('2D #1.1:',sum(fail),0);
0319 unit_test_cmp('2D #1.2(r=.1):',vol*c2f/VV,1,1e-2);
0320
0321 fmdl = ng_mk_cyl_models([2,1,.1],[16,1],.03);
0322 fmdl.nodes(:,3) = fmdl.nodes(:,3) - 1;
0323 vol = get_elem_volume(fmdl)';
0324 xyzr = ones(4,1)*linspace(-.5,.5,7);
0325
0326 rr = .1; VV = pi*4/3*rr^3; xyzr(4,:) = rr;
0327 [c2f,fail] = mk_c2f_circ_mapping(fmdl,xyzr);
0328 unit_test_cmp('3D #1.1:',sum(fail),0);
0329 unit_test_cmp('3D #1.2(r=.1):',vol*c2f/VV,1,1e-2);
0330
0331 rr = .01; VV = pi*4/3*rr^3; xyzr(4,:) = rr;
0332 [c2f,fail] = mk_c2f_circ_mapping(fmdl,xyzr);
0333 unit_test_cmp('3D #1.1(r=.01):',sum(fail),0);
0334 unit_test_cmp('3D #1.2:',vol*c2f/VV,1,1e-2);
0335
0336
0337 imdl = mk_common_model('a2c2',16); fmdl=imdl.fwd_model;
0338 xyc = [0,0.27,0.18;0,-0.1,0.03;0,0.1,0.2;0.1,0.37,0.1]';
0339 th=linspace(0,2*pi,20)';
0340 xx=[0*th+1]*xyc(1,:)+sin(th)*xyc(3,:);
0341 yy=[0*th+1]*xyc(2,:)+cos(th)*xyc(3,:);
0342 show_fem(fmdl,[0,0,1]); set(line(xx,yy),'LineWidth',2);
0343
0344
0345 rr= 0.1;c2f= mk_c2f_circ_mapping( fmdl, [0;0;rr] );
0346 tt= zeros(size(c2f)); tt(1:4) = pi*rr^2/4; tt= tt./get_elem_volume(fmdl);
0347 unit_test_cmp('2D ex 1:',c2f,tt,1e-10);
0348
0349
0350 rr= 0.03;c2f= mk_c2f_circ_mapping( fmdl, [.0;.05;rr]);
0351 tt= zeros(size(c2f)); tt(1) = pi*rr^2; tt= tt./get_elem_volume(fmdl);
0352 unit_test_cmp('2D ex 2:',c2f,tt,1e-10);
0353
0354
0355 imdl = mk_common_model('a3cr',16); fmdl=imdl.fwd_model;
0356 fmdl.nodes = 1.1*fmdl.nodes;
0357 rr=0.1;c2f= mk_c2f_circ_mapping( fmdl, [0;0;rr]);
0358 V = pi*rr^2*(max(fmdl.nodes(:,3)) - min(fmdl.nodes(:,3)));
0359 unit_test_cmp('3D ex 1 (cylinder):',get_elem_volume(fmdl)'*c2f,V,1e-2);
0360
0361
0362 imdl = mk_common_model('a3cr',16); fmdl=imdl.fwd_model;
0363 rr=0.05;c2f= mk_c2f_circ_mapping( fmdl, [0;0;0;rr]);
0364 tt = 4/3*pi*rr^3/24./get_elem_volume(fmdl);
0365 unit_test_cmp('3D ex 2a:',c2f(193:196),tt(193:196),1e-10);
0366 unit_test_cmp('3D ex 2b:',c2f(1:64),0);
0367
0368 imdl = mk_common_model('a3cr',16); fmdl=imdl.fwd_model;
0369 rr=0.05;c2f= mk_c2f_circ_mapping( fmdl, [0 0;0 0;0 0;rr,rr]);
0370 unit_test_cmp('3D ex 3a:',c2f(193:196,:),tt(193:196)*[1,1],1e-10);
0371 unit_test_cmp('3D ex 3b:',c2f(1:64,:),0);