0001 function [mapping, outside] = mk_analytic_c2f( f_mdl, c_mdl, opt)
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
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039 if ischar(f_mdl) && strcmp(f_mdl, 'UNIT_TEST'); do_unit_test; return; end
0040
0041 if ischar(f_mdl) && strcmp(f_mdl, 'LOAD'); preload; return; end
0042
0043 if nargin== 2, opt = struct; end
0044
0045 opt = assign_defaults( c_mdl, f_mdl, opt );
0046
0047 copt.cache_obj = cache_obj(c_mdl, f_mdl, opt);
0048 copt.fstr = 'mk_analytic_c2f';
0049
0050 [mapping, outside] = eidors_cache(@mapping_calc,{f_mdl,c_mdl,opt},copt);
0051
0052
0053
0054 function [mapping, outside] = mapping_calc(f_mdl, c_mdl, opt)
0055
0056 f_mdl= offset_and_project( f_mdl, opt);
0057
0058 f_dim = elem_dim(f_mdl);
0059 c_dim = elem_dim(c_mdl);
0060 d_num = f_dim * 10 + c_dim;
0061
0062 switch d_num
0063 case 33
0064 mapping = mk_tet_c2f(f_mdl,c_mdl, opt);
0065 case 22
0066 mapping = mk_tri_c2f(f_mdl,c_mdl, opt);
0067 case 32
0068 mapping = mk_tri2tet_c2f(f_mdl, c_mdl, opt);
0069 case 23
0070 mapping = mk_tri2tet_c2f(c_mdl, f_mdl, opt);
0071 mapping = bsxfun(@times, mapping , get_elem_volume(c_mdl));
0072 if isinf(opt.z_depth)
0073 height = max(c_mdl.nodes(:,3)) - min(c_mdl.nodes(:,3));
0074 else
0075 height = opt.z_depth;
0076 end
0077 mapping = mapping * height;
0078 mapping = bsxfun(@rdivide, mapping', get_elem_volume(f_mdl));
0079 otherwise
0080 error('EIDORS:WrongDim',['Unsupported combination of dimensions: ' ...
0081 'c_mdl=%d, f_mdl=%d'],c_dim,f_dim);
0082 end
0083
0084
0085 if isfield(c_mdl,'coarse2fine')
0086 mapping = mapping*c_mdl.coarse2fine;
0087 end
0088
0089 if nargout>1;
0090 outside = 1 - sum(mapping,2);
0091 end
0092
0093
0094
0095 function c_obj = cache_obj(c_mdl, f_mdl, opt)
0096 c_obj = {c_mdl.nodes, c_mdl.elems, ...
0097 f_mdl.nodes, f_mdl.elems, opt};
0098
0099
0100 function f_mdl= offset_and_project( f_mdl, opt)
0101 [fn,fd]= size(f_mdl.nodes);
0102 T= opt.f2c_offset;
0103 M= opt.f2c_project;
0104
0105 f_mdl.nodes= (M*( f_mdl.nodes - ones(fn,1)*T )')';
0106
0107 function opt = assign_defaults( c_mdl, f_mdl, org )
0108 opt = struct;
0109 try opt = c_mdl.mk_coarse_fine_mapping; end
0110 fn = fieldnames(org);
0111 for f = 1:numel(fn)
0112 opt.(fn{f}) = org.(fn{f});
0113 end
0114 [fn,fd]= size(f_mdl.nodes);
0115 try opt.f2c_offset;
0116 catch opt.f2c_offset= zeros(1,fd);
0117 end
0118 try opt.f2c_project;
0119 catch opt.f2c_project= speye(fd);
0120 end
0121 try opt.z_depth;
0122 catch opt.z_depth= inf;
0123 end
0124
0125
0126
0127 function do_unit_test
0128 ll = eidors_msg('log_level', 1);
0129 do_original_2d_tests
0130 test_2d3d_handling
0131 mk_tri_c2f UNIT_TEST
0132 mk_tet_c2f UNIT_TEST
0133 mk_tri2tet_c2f UNIT_TEST
0134 eidors_msg('log_level',ll);
0135
0136 function test_2d3d_handling
0137 tet = mk_grid_model([],[0 1],[0 1],[0 1]);
0138 tet = rmfield(tet,'coarse2fine');
0139 tri = mk_grid_model([],[0 1],[0 1]);
0140 tri = rmfield(tri,'coarse2fine');
0141
0142 c2f_a = mk_analytic_c2f(tri,tet);
0143 c2f_a = bsxfun(@times, c2f_a, get_elem_volume(tri));
0144 c2f_b = mk_analytic_c2f(tet,tri);
0145 c2f_b = bsxfun(@times, c2f_b, get_elem_volume(tet));
0146
0147 unit_test_cmp('2d3d:01',sum(c2f_a(:)), 1,eps);
0148 unit_test_cmp('2d3d:02',sum(c2f_b(:)), 1,eps);
0149 unit_test_cmp('2d3d:03',c2f_a,c2f_b',eps)
0150
0151
0152
0153 function do_original_2d_tests
0154 fmdl = mk_circ_tank(2,[],2); fmdl.nodes = fmdl.nodes*2;
0155 cmdl = mk_circ_tank(2,[],2); cmdl.nodes = cmdl.nodes*2;
0156 c2f = mk_analytic_c2f( fmdl, cmdl);
0157 unit_test_cmp('t1',c2f,eye(16),eps)
0158
0159 fmdl = mk_circ_tank(3,[],2);
0160 fmdl.nodes = fmdl.nodes*3;
0161 c2f = mk_analytic_c2f( fmdl, cmdl);
0162 unit_test_cmp('t2',c2f,[eye(16);zeros(20,16)],eps)
0163
0164 fmdl = mk_circ_tank(2,[],2); fmdl.nodes = fmdl.nodes*2;
0165 cmdl = mk_circ_tank(1,[],2); cmdl.nodes = cmdl.nodes*1;
0166 c2f = mk_analytic_c2f( fmdl, cmdl);
0167 unit_test_cmp('t3',c2f,[eye(4);zeros(12,4)],eps)
0168
0169 cmdl = mk_circ_tank(1,[],2); cmdl.nodes = cmdl.nodes*0.8;
0170 c2f = mk_analytic_c2f( fmdl, cmdl);
0171 unit_test_cmp('t4',c2f,[eye(4)*.64;zeros(12,4)], eps)
0172
0173
0174 fmdl = mk_circ_tank(10,[],2);
0175 cmdl = mk_circ_tank(8,[],2);
0176 c2f = mk_analytic_c2f( fmdl, cmdl);
0177 unit_test_cmp('t6',sum(c2f(1:324,:)'),ones(1,324),1e-14);
0178
0179 cmdl.nodes = cmdl.nodes*0.95;
0180
0181 c2f = mk_analytic_c2f( fmdl, cmdl);
0182
0183
0184 function preload
0185
0186
0187 electrodes_per_plane = 16;
0188 number_of_planes = 2;
0189 tank_radius = 0.2;
0190 tank_height = 0.5;
0191 fine_mdl = ng_mk_cyl_models([tank_height,tank_radius],...
0192 [electrodes_per_plane,0.15,0.35],[0.01]);
0193
0194
0195 coarse_mdl_maxh = 0.07;
0196 coarse_mdl = ng_mk_cyl_models([tank_height,tank_radius,coarse_mdl_maxh],[0],[]);
0197
0198 disp('Calculating coarse2fine mapping ...');
0199 inv3d.fwd_model.coarse2fine = ...
0200 mk_analytic_c2f( fine_mdl, coarse_mdl);
0201 disp(' ... done');