0001 function s_mat= system_mat_1st_order( fwd_model, img)
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014 if ischar(fwd_model) && strcmp(fwd_model,'UNIT_TEST'); do_unit_test; return; end
0015
0016 if nargin == 1
0017 img= fwd_model;
0018 elseif strcmp(getfield(warning('query','EIDORS:DeprecatedInterface'),'state'),'on')
0019 warning('EIDORS:DeprecatedInterface', ...
0020 ['Calling SYSTEM_MAT_1ST_ORDER with two arguments is deprecated and will cause' ...
0021 ' an error in a future version. First argument ignored.']);
0022 end
0023 fwd_model= img.fwd_model;
0024
0025
0026 if isfield(img,'current_params') && ...
0027 (~ischar(img.current_params) || ~strcmp(img.current_params,'conductivity'))
0028 if ischar(img.current_params)
0029 error('system_mat_1st_order does not work for %s',img.current_params);
0030 else
0031 img.current_params
0032 error('system_mat_1st_order does not work for the above');
0033 end
0034 end
0035
0036 FC= system_mat_fields( fwd_model);
0037 lFC= size(FC,1);
0038 ED = elem_dim(fwd_model);
0039 lNE= ED*num_elems(fwd_model);
0040
0041 elem_data = check_elem_data(fwd_model, img);
0042 if size(elem_data,3) == 1
0043
0044 elem_sigma = kron( elem_data, ones(ED,1) );
0045 elem_sigma(end+1:lFC) = 1;
0046
0047 ES= spdiags(elem_sigma,0,lFC,lFC);
0048 else
0049 switch elem_dim(fwd_model)
0050 case 2;
0051 idx = 1:2:lNE;
0052 ES= sparse([idx,idx+1,idx,idx+1]', ...
0053 [idx,idx,idx+1,idx+1]', elem_data(:), lFC,lFC);
0054
0055 ES(lNE+1:lFC,lNE+1:lFC) = speye(lFC-lNE);
0056 case 3;
0057 idx = 1:3:lNE;
0058 ES= sparse([idx,idx+1,idx+2,idx,idx+1,idx+2,idx,idx+1,idx+2]', ...
0059 [idx,idx,idx,idx+1,idx+1,idx+1,idx+2,idx+2,idx+2]', ...
0060 elem_data(:), lFC,lFC);
0061
0062 ES(lNE+1:lFC,lNE+1:lFC) = speye(lFC-lNE);
0063 otherwise;
0064 error('%d D anisotropic elements not implemented', elem_dim(fwd_model));
0065 end
0066
0067 end
0068
0069
0070
0071 E= FC.' * ES * FC;
0072
0073
0074 s_mat.E= 1/2*(E.' + E);
0075
0076 function elem_data = check_elem_data(fwd_model, img);
0077 elem_data = img.elem_data;
0078 sz_elem_data = size(elem_data);
0079 if sz_elem_data(2) ~= 1;
0080 error('system_mat_1st_order: can only solve one image (sz_elem_data=%)', ...
0081 sz_elem_data);
0082 end
0083
0084 if isfield(fwd_model, 'coarse2fine');
0085 c2f = fwd_model.coarse2fine;
0086 sz_c2f = size(c2f);
0087 switch sz_elem_data(1)
0088 case sz_c2f(1);
0089 case sz_c2f(2); elem_data = c2f * elem_data;
0090 if isfield(fwd_model, 'background')
0091 elem_data = elem_data + fwd_model.background;
0092 end
0093
0094 otherwise;
0095 error(['system_mat_1st_order: provided elem_data ' ...
0096 ' (sz=%d) does not match c2f (sz=[%d %d])'], ...
0097 sz_elem_data(1), sz_c2f(1), sz_c2f(2));
0098 end
0099 else
0100 if sz_elem_data(1) ~= num_elems(fwd_model)
0101 error(['system_mat_1st_order: provided elem_data (sz=%d) does ' ...
0102 ' not match fwd_model (sz=%d)'], sz_elem_data(1), num_elems(fwd_model));
0103 end
0104 end
0105
0106
0107
0108
0109
0110 function do_unit_test
0111 imdl= mk_common_model('a2c2',16);
0112 img= mk_image(imdl);
0113 S1 = system_mat_1st_order(img.fwd_model,img);
0114 unit_test_cmp('sys_mat1', S1.E(1,:), [4,-1,-1,-1,-1,zeros(1,36)],1e-14);
0115
0116 img.elem_data([1:16]) = 2;
0117 img.calc_colours.clim = 4; show_fem(img,[0,0,3]);
0118
0119 S2 = system_mat_1st_order(img.fwd_model,img);
0120 unit_test_cmp('sys_mat2', S2.E(1,:), 2*[4,-1,-1,-1,-1,zeros(1,36)],1e-14);
0121
0122 imdl= mk_common_model('a2C2',16);
0123 img= mk_image(imdl);
0124 S1 = system_mat_1st_order(img.fwd_model,img);
0125 unit_test_cmp('sys_mat1', S1.E(1,:), [4,-1,-1,-1,-1,zeros(1,52)],1e-14);
0126
0127 img.elem_data([1:16]) = 2;
0128 img.calc_colours.clim = 4; show_fem(img,[0,0,3]);
0129
0130 S2 = system_mat_1st_order(img.fwd_model,img);
0131 unit_test_cmp('sys_mat2', S2.E(1,:), 2*[4,-1,-1,-1,-1,zeros(1,52)],1e-14);
0132
0133 idx = 41-(0:15);
0134 unit_test_cmp('sys_mat4', S2.E(idx,idx), S1.E(idx,idx),1e-14);
0135 idx = 1:5;
0136 unit_test_cmp('sys_mat3', S2.E(idx,idx), 2*S1.E(idx,idx),1e-14);
0137
0138 img.elem_data([1:36]) = 2;
0139 S2 = system_mat_1st_order(img.fwd_model,img);
0140 idx = 1:5;
0141 unit_test_cmp('sys_mat3', S2.E(idx,idx), 2*S1.E(idx,idx),1e-14);
0142
0143 img.elem_data = ones(63,1);
0144 try
0145
0146 S2 = system_mat_1st_order(img.fwd_model,img);
0147 unit_test_cmp('sys_mat: test for size error', 1,0);
0148 catch
0149 unit_test_cmp('sys_mat: test for size error', 1,1);
0150 end
0151
0152 imdl= mk_common_model('a2c2',16);
0153 cmdl = mk_circ_tank(4,[],0);
0154 c2f = mk_coarse_fine_mapping( img.fwd_model, cmdl);
0155 img.fwd_model.coarse2fine = c2f;
0156 img.elem_data = ones(size(cmdl.elems,1),1);
0157 S3 = system_mat_1st_order(img.fwd_model,img);
0158 unit_test_cmp('c2f #1', S1.E, S3.E,1e-14);
0159
0160 cmdl = mk_circ_tank(2,[],0);
0161 c2f = mk_coarse_fine_mapping( img.fwd_model, cmdl);
0162 c2f = c2f./(sum(c2f,2) * ones(1,size(c2f,2)));
0163 img.fwd_model.coarse2fine = c2f;
0164 img.elem_data = ones(size(cmdl.elems,1),1);
0165 S4 = system_mat_1st_order(img.fwd_model,img);
0166 unit_test_cmp('c2f #2', S1.E, S4.E,1e-14);
0167
0168 test_2d_resistor
0169 test_3d_resistor
0170
0171 function test_2d_resistor
0172 nn= 12;
0173 ww=2;
0174 conduc= .4;
0175 current= 4;
0176 z_contact= 9e-1;
0177 scale = .35;
0178 mdl=mk_grid_model([],3+scale*(1:ww), scale*(1:nn/ww));
0179 mdl= rmfield(mdl,'coarse2fine');
0180
0181 mdl.gnd_node = 1;
0182 elec_nodes= [1:ww];
0183 elec(1).nodes= elec_nodes; elec(1).z_contact= z_contact;
0184 elec(2).nodes= nn-elec_nodes+1; elec(2).z_contact= z_contact;
0185 stim.stim_pattern= [-1;1]*current;
0186 stim.meas_pattern= [-1,1];
0187 mdl.stimulation= stim;
0188 mdl.electrode= elec;
0189 mdl.normalize_measurements = 0;
0190
0191
0192
0193 wid_len= max(mdl.nodes) - min(mdl.nodes);
0194 R = wid_len(2) / wid_len(1) / conduc + 2*z_contact/scale;
0195
0196 V= current*R;
0197
0198
0199
0200 mdl.solve = @fwd_solve_1st_order;
0201 mdl.system_mat = @system_mat_1st_order;
0202 img = mk_image(mdl, conduc);
0203 fsol= fwd_solve(img);
0204
0205 unit_test_cmp('test 2d vs analytic', fsol.meas, V, 1e-11);
0206
0207
0208 mdl.solve = @np_fwd_solve;
0209 mdl.system_mat = @np_calc_system_mat;
0210 img = mk_image(mdl, conduc);
0211 fsol= fwd_solve(img);
0212
0213 unit_test_cmp('np_fwd_solve vs analytic', fsol.meas, V, 1e-11);
0214
0215 function test_3d_resistor
0216 ll=5;
0217 ww=1;
0218 hh=1;
0219 conduc= .13;
0220 current= 4;
0221 z_contact= 9e-1;
0222 scale = .46;
0223 nn=0;
0224 for z=0:ll; for x=0:ww; for y=0:hh
0225 nn=nn+1;
0226 mdl.nodes(nn,:) = [x,y,z];
0227 end; end; end
0228
0229 mdl= mk_grid_model([],0:ww,0:hh,0:ll);
0230 mdl.nodes= mdl.nodes*scale;
0231 mdl= rmfield(mdl,'coarse2fine');
0232 mdl.boundary= find_boundary(mdl.elems);
0233 mdl.gnd_node = 1;
0234 mdl.normalize_measurements = 0;
0235 elec_nodes= [1:(ww+1)*(hh+1)];
0236 elec(1).nodes= elec_nodes; elec(1).z_contact= z_contact;
0237 elec(2).nodes= nn-elec_nodes+1; elec(2).z_contact= z_contact;
0238 stim.stim_pattern= [-1;1]*current;
0239 stim.meas_pattern= [-1,1];
0240 mdl.stimulation= stim;
0241 mdl.electrode= elec;
0242
0243
0244
0245 R = ll / ww / hh / scale/ conduc + 2*z_contact/scale^2;
0246
0247 V= current*R;
0248
0249
0250 mdl.solve = @fwd_solve_1st_order;
0251 mdl.system_mat = @system_mat_1st_order;
0252
0253 img= mk_image(mdl, conduc);
0254
0255 fsol= fwd_solve(img);
0256
0257 unit_test_cmp('test 2d vs analytic', fsol.meas, V, 1e-11);
0258
0259 mdl.solve = @np_fwd_solve;
0260 mdl.system_mat = @np_calc_system_mat;
0261 mdl.misc.perm_sym= '{n}';
0262 img= mk_image(mdl, conduc);
0263
0264 fsol= fwd_solve(img);
0265
0266 unit_test_cmp('np_fwd_solve vs analytic', fsol.meas, V, 1e-11);