0001 function[data] = fwd_solve_higher_order(fwd_model,img)
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 if ischar(fwd_model) && strcmp(fwd_model,'UNIT_TEST'); do_unit_test; return; end
0033
0034 if nargin == 1
0035 img= fwd_model;
0036 elseif strcmp(getfield(warning('query','EIDORS:DeprecatedInterface'),'state'),'on')
0037 warning('EIDORS:DeprecatedInterface', ...
0038 ['Calling FWD_SOLVE_HIGHER_ORDER with two arguments is deprecated and will cause' ...
0039 ' an error in a future version. First argument ignored.']);
0040 end
0041
0042 fwd_model= img.fwd_model;
0043
0044
0045 if ~isfield(fwd_model,'approx_type') || ...
0046 strcmp(fwd_model.approx_type,'tri3') || ...
0047 strcmp(fwd_model.approx_type,'tet4')
0048
0049 else
0050 [bound,elem,nodes] = fem_1st_to_higher_order(fwd_model);
0051 fwd_model.boundary=bound; fwd_model.elems=elem; fwd_model.nodes=nodes;
0052
0053 img.fwd_model=fwd_model;
0054 end
0055
0056
0057 s_mat = calc_system_mat(img); At=s_mat.E;
0058
0059
0060
0061
0062 elecstruc=fwd_model.electrode; nelecs=size(elecstruc,2);
0063 stimstruc=fwd_model.stimulation; nstims=size(stimstruc,2);
0064 nodestruc=fwd_model.nodes; nnodes=size(nodestruc,1);
0065
0066
0067 nmeass=0;
0068 for k=1:nstims
0069 stimkmeasmatrix = stimstruc(k).meas_pattern;
0070 nmeass=nmeass+size(stimkmeasmatrix,1);
0071 end
0072
0073
0074
0075 elecnode=zeros(1,nelecs);
0076 if(size(elecstruc(1).nodes,2)==1 && size(elecstruc(1).nodes,1)==1)
0077 for i=1:nelecs
0078
0079 elecnode(i)=elecstruc(i).nodes;
0080 end
0081
0082 rhsdata=zeros(nnodes,nstims);
0083 nodeunknowns=zeros(nnodes,nstims);
0084 else
0085 for i=1:nelecs
0086
0087 elecnode(i)=nnodes+i;
0088 end
0089
0090 rhsdata=zeros(nnodes+nelecs,nstims);
0091 nodeunknowns=zeros(nnodes+nelecs,nstims);
0092 end
0093
0094
0095 for ii=1:nstims
0096
0097 curnode=stimstruc(ii).stim_pattern;
0098 for i=1:nelecs
0099 rhsdata(elecnode(i),ii)=curnode(i);
0100 end
0101 end
0102
0103
0104 groundnode=fwd_model.gnd_node; idx=1:size(At,1); idx(groundnode)=[];
0105
0106
0107 nodeunknowns(idx,:)=left_divide(At(idx,idx),rhsdata(idx,:));
0108
0109
0110
0111
0112 velec=zeros(nelecs,nstims);
0113 for i=1:nelecs
0114
0115 velec(i,:)=nodeunknowns(elecnode(i),:);
0116 end
0117
0118
0119 vmeaselec=zeros(nmeass,1); idx=0;
0120 for ii=1:nstims
0121
0122 meas_pat=conj(stimstruc(ii).meas_pattern);
0123 n_meas=size(meas_pat,1);
0124 vmeaselec(idx + (1:n_meas) ) = meas_pat*velec(:,ii);
0125 idx=idx+n_meas;
0126 end
0127
0128
0129 data.meas= vmeaselec;
0130 data.time= NaN;
0131 data.name= 'solved by fwd_solve_higher_order';
0132 data.quantity = 'voltage';
0133 try; if img.fwd_solve.get_all_meas == 1
0134 data.volt = nodeunknowns(1:nnodes,:);
0135 end; end
0136 try; if img.fwd_solve.get_all_nodes== 1
0137 data.volt = nodeunknowns;
0138 end; end
0139
0140
0141 end
0142
0143 function do_unit_test
0144 tol = 1e-13;
0145 vve = do_unit_test_2D;
0146 vve_ref = [
0147 0.898225115241117 0.921510761628436 0.928516596253320
0148 0.406398239528486 0.412406966923347 0.413938179536629
0149 0.248067950415984 0.250212111398160 0.250609888163540
0150 0.179592593985273 0.179643951982781 0.179734695991927];
0151
0152 unit_test_cmp('2D: 1st order',vve(1:4,1),vve_ref(1:4,1),tol);
0153 unit_test_cmp('2D: 2nd order',vve(1:4,2),vve_ref(1:4,2),tol);
0154 unit_test_cmp('2D: 3rd order',vve(1:4,3),vve_ref(1:4,3),tol);
0155 vve = do_unit_test_3D;
0156 vve_ref = [
0157 1.404189968566952 1.410900674463290
0158 0.403207625837809 0.402992578774667
0159 0.198517193844915 0.201211971071238
0160 0.133852904079284 0.133841105904217];
0161 unit_test_cmp('3D: 1st order',vve(1:4,1),vve_ref(1:4,1),tol);
0162 unit_test_cmp('3D: 2nd order',vve(1:4,2),vve_ref(1:4,2),tol);
0163
0164 end
0165 function [vve] = do_unit_test_2D
0166 imdl = mk_common_model('c2C',16); img = mk_image(imdl.fwd_model,1);
0167 vv=fwd_solve(img); v0e=vv.meas;
0168
0169
0170 img.fwd_model.solve = @fwd_solve_higher_order;
0171 img.fwd_model.system_mat = @system_mat_higher_order;
0172
0173 vve=[]; JJ4=[];
0174 for i= 1:3; switch i;
0175 case 1; img.fwd_model.approx_type = 'tri3';
0176 case 2; img.fwd_model.approx_type = 'tri6';
0177 case 3; img.fwd_model.approx_type = 'tri10';
0178 end
0179 vv=fwd_solve(img); vve(:,i)=vv.meas;
0180 end
0181
0182 subplot(321);
0183 plot([v0e,vve,(v0e*[1,1,1]-vve)*10]);
0184 legend('Default','linear','quadratic','cubic','(1-0)x10','(2-0)x10','(3-0)x10');
0185 xlim([1,100]);
0186 end
0187 function vve=do_unit_test_3D;
0188 imdl = mk_common_model('b3cr',16); img = mk_image(imdl.fwd_model,1);
0189 vv=fwd_solve(img); v0e=vv.meas;
0190
0191
0192 img.fwd_model.solve = @fwd_solve_higher_order;
0193 img.fwd_model.system_mat = @system_mat_higher_order;
0194
0195 vve=[]; JJ4=[];
0196 for i= 1:2; switch i;
0197 case 1; img.fwd_model.approx_type = 'tet4';
0198 case 2; img.fwd_model.approx_type = 'tet10';
0199 end
0200 vv=fwd_solve(img); vve(:,i)=vv.meas;
0201 end
0202
0203 subplot(322);
0204 plot([v0e,vve,(v0e*[1,1]-vve)*10]);
0205 legend('Default','linear','quadratic','(1-0)x10','(2-0)x10');
0206 xlim([1,100]);
0207
0208 end