0001 function [s_mat]=system_mat_higher_order(fwd_model,img)
0002
0003
0004
0005 if ischar(fwd_model) && strcmp(fwd_model,'UNIT_TEST'); do_unit_test; return; end
0006
0007 if nargin == 1
0008 img= fwd_model;
0009 elseif strcmp(getfield(warning('query','EIDORS:DeprecatedInterface'),'state'),'on')
0010 warning('EIDORS:DeprecatedInterface', ...
0011 ['Calling SYSTEM_MAT_HIGHER_ORDER with two arguments is deprecated and will cause' ...
0012 ' an error in a future version. First argument ignored.']);
0013 end
0014 fwd_model= img.fwd_model;
0015
0016
0017 elecstruc=fwd_model.electrode; nelecs=size(elecstruc,2);
0018 nodestruc=fwd_model.nodes; nnodes=size(nodestruc,1);
0019
0020
0021 if isfield(elecstruc,'faces');
0022 error('Can''t process faces-type electrodes. See mat_idx_to_electrode for help');
0023 end
0024 if(size(elecstruc(1).nodes,2)==1 && size(elecstruc(1).nodes,1)==1)
0025
0026 [At,elemstiff]=mc_calc_stiffness(fwd_model,img);
0027 else
0028 [Am,elemstiff]=mc_calc_stiffness(fwd_model,img);
0029
0030 [Aw,Az,Ad]=mc_calc_complete(fwd_model);
0031 At=sparse(nnodes+nelecs,nnodes+nelecs);
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041 At(1:nnodes,1:nnodes) = Am+Az;
0042 At(1:nnodes,nnodes+1:nnodes+nelecs) = Aw;
0043 At(nnodes+1:nnodes+nelecs,1:nnodes)=Aw';
0044 At(nnodes+1:nnodes+nelecs,nnodes+1:nnodes+nelecs)=Ad;
0045 end
0046
0047
0048 s_mat.E=sparse(At);
0049
0050
0051 s_mat.elemstiff=elemstiff;
0052 end
0053
0054
0055 function [Agal,elemstiff]=mc_calc_stiffness(fwd_model,img)
0056
0057
0058
0059
0060 if(nargin==1)
0061 img=fwd_model; fwd_model=img.fwd_model;
0062 end
0063
0064
0065
0066 nodestruc=fwd_model.nodes; nodedim=size(nodestruc,2); nnodes=size(nodestruc,1);
0067 elemstruc=fwd_model.elems; nelems=size(elemstruc,1);
0068
0069
0070 eletype=fwd_model.approx_type;
0071 if(strcmp(eletype,'tri3'))
0072 dim=2; order=0;
0073 elseif(strcmp(eletype,'tri6'))
0074 dim=2; order=2;
0075 elseif(strcmp(eletype,'tri10'))
0076 dim=2; order=4;
0077 elseif(strcmp(eletype,'tet4'))
0078 dim=3; order=0;
0079 elseif(strcmp(eletype,'tet10'))
0080 dim=3; order=2;
0081 else
0082 error('Element type not recognised for integration rules');
0083 end
0084 [weight,xcoord,ycoord,zcoord]=gauss_points(dim,order);
0085
0086
0087 for kk=size(weight,2):-1:1
0088 dphi(:,:,kk) = element_d_shape_function(eletype,xcoord(kk),ycoord(kk),zcoord(kk));
0089 end
0090
0091
0092
0093
0094
0095 for i=nelems:-1:1
0096
0097 eleminodelist=elemstruc(i,:);
0098
0099
0100 thise = nodestruc(eleminodelist,:);
0101
0102
0103 if(nodedim==2); jacobianelem = ...
0104 [thise(2,1)-thise(1,1),thise(2,2)-thise(1,2); ...
0105 thise(3,1)-thise(1,1),thise(3,2)-thise(1,2)];
0106 elseif(nodedim==3); jacobianelem = ...
0107 [thise(2,1)-thise(1,1),thise(2,2)-thise(1,2),thise(2,3)-thise(1,3); ...
0108 thise(3,1)-thise(1,1),thise(3,2)-thise(1,2),thise(3,3)-thise(1,3); ...
0109 thise(4,1)-thise(1,1),thise(4,2)-thise(1,2),thise(4,3)-thise(1,3)];
0110 end
0111
0112
0113
0114 magjacelem=abs(det(jacobianelem));
0115
0116
0117 Ammat=0;
0118 for kk=1:size(weight,2)
0119
0120
0121
0122 jdphitemp=jacobianelem\dphi(:,:,kk);
0123 Ammat = Ammat + weight(kk)* ...
0124 (jdphitemp'*jdphitemp)*magjacelem;
0125 end
0126
0127
0128
0129
0130
0131 elemstiff(i).elemstiff=Ammat;
0132
0133
0134
0135 stiff=Ammat*img.elem_data(i);
0136
0137
0138
0139
0140 ll = length(eleminodelist);
0141 ii = eleminodelist(ones(ll,1),:); jj=ii';
0142 idx = (i-1)*ll^2 + (1:ll^2);
0143 AI(idx) = ii(:);
0144 AJ(idx) = jj(:);
0145 Aval(idx) = stiff(:);
0146
0147 end
0148
0149 Agal= sparse(AI, AJ, Aval, nnodes, nnodes);
0150 end
0151
0152
0153 function [Aw,Az,Ad]=mc_calc_complete(fwd_model)
0154
0155
0156
0157
0158
0159 elecstruc=fwd_model.electrode; nelecs=size(elecstruc,2);boundstruc=fwd_model.boundary; nodestruc=fwd_model.nodes;
0160 nnodes=size(nodestruc,1); nodedim=size(nodestruc,2);
0161
0162
0163
0164
0165
0166
0167
0168 eletype=fwd_model.approx_type;
0169 if(strcmp(eletype,'tri3'))
0170 dim=1; order=2;
0171 elseif(strcmp(eletype,'tri6'))
0172 dim=1; order=4;
0173 elseif(strcmp(eletype,'tri10'))
0174 dim=1; order=6;
0175 elseif(strcmp(eletype,'tet4'))
0176 dim=2; order=2;
0177 elseif(strcmp(eletype,'tet10'))
0178 dim=2; order=4;
0179 else
0180 error('Element type not recognised for integration rules');
0181 end
0182 [weight,xcoord,ycoord]=gauss_points(dim,order);
0183
0184
0185 for kk=size(weight,2):-1:1
0186 phi(:,kk) = boundary_shape_function(eletype,xcoord(kk),ycoord(kk))';
0187 end
0188
0189
0190 Az=sparse(nnodes,nnodes);
0191 Aw=zeros(nnodes,nelecs); Ad=zeros(nelecs,nelecs);
0192
0193
0194 for ke=1:nelecs
0195
0196 [bdy_idx,bdy_area]=find_electrode_bdy(boundstruc(:,1:nodedim),nodestruc,elecstruc(ke).nodes);
0197
0198
0199 boundidx_ke=bdy_idx; area_ke=bdy_area;
0200
0201
0202 elecimped=elecstruc(ke).z_contact;
0203
0204
0205 elecarea=0;
0206 for i=1:size(area_ke,2)
0207 elecarea = elecarea + abs(area_ke(i));
0208 end
0209
0210
0211 Ad(ke,ke)=elecarea/elecimped;
0212
0213
0214
0215 for ii=1:length(boundidx_ke)
0216
0217 thisb=nodestruc(boundstruc(boundidx_ke(ii),:),:);
0218
0219
0220
0221 if(nodedim==2)
0222
0223 diff21=thisb(2,:)-thisb(1,:);
0224 magjacbound=0.5*sqrt(diff21(1)^2+diff21(2)^2);
0225 elseif(nodedim==3)
0226
0227 diffprod=cross(thisb(3,:)-thisb(1,:),thisb(3,:)-thisb(2,:));
0228 magjacbound=sqrt(diffprod(1)^2+diffprod(2)^2+diffprod(3)^2);
0229 end
0230
0231
0232 Azmat=0; Awmat=0;
0233 for kk=1:size(weight,2)
0234 temphikk = phi(:,kk);
0235 Azmat = Azmat + weight(kk)* ...
0236 (temphikk*temphikk')*magjacbound;
0237 Awmat = Awmat + weight(kk)* ...
0238 (phi(:,kk))'*magjacbound;
0239
0240
0241
0242
0243
0244 end
0245
0246
0247 boundnodes=boundstruc(boundidx_ke(ii),:);
0248
0249
0250 Az(boundnodes,boundnodes) = Az(boundnodes,boundnodes)+Azmat/elecimped;
0251 Aw(boundnodes,ke) = Aw(boundnodes,ke) - Awmat'/elecimped;
0252 end
0253
0254 end
0255
0256 end
0257
0258 function do_unit_test
0259 for i=0:100 ; switch i
0260 case 0;img = mk_image( mk_common_model('c2C2',16),1);
0261 str = 'c2C2';
0262 tst= [4,[1,1,1]/3];
0263 ap0 = 'tri3'; ap1 = 'tri6';
0264 case 1;img = mk_image( mk_common_model('b3cr',16),1);
0265 str = 'b3cr';
0266 tst= [0.268642857142857,0.028,0.009333333333333,0.028];
0267 ap0 = 'tet4'; ap1 = 'tet10';
0268 case 2;img = mk_image( ng_mk_cyl_models(1,[6,0.5],.1),1);
0269 str = 'ng_mk_cyl1';
0270 tst= [0.131643427733397,0.000323024820911,0,0];
0271 ap0 = 'tet4'; ap1 = 'tet10';
0272 case 3;img = mk_image( mk_common_model('d3cr',16),1);
0273 str = 'd3cr';
0274 tst= [0.11125, 0.01, 0.003333333333333,0.01];
0275 ap0 = 'tet4'; ap1 = 'tet10';
0276 case 4;img = mk_image( ng_mk_cyl_models([1,1,.1],[6,0.5],.1),1);
0277 str = 'ng_mk_cyl2';
0278 tst= [0.061014587493642, 0.000551387020511, 0, 0];
0279 ap0 = 'tet4'; ap1 = 'tet10';
0280 case 5;break
0281 end
0282
0283 img.fwd_model.approx_type = ap0;
0284 S1= system_mat_1st_order( img );
0285 Sl= system_mat_higher_order( img );
0286 unit_test_cmp(['Linear ',str], S1.E, Sl.E, 1e-13)
0287
0288 img.fwd_model.approx_type = ap1;
0289 img.fwd_model.system_mat = @system_mat_higher_order;
0290 [img.fwd_model.boundary,img.fwd_model.elems,img.fwd_model.nodes] = ...
0291 fem_1st_to_higher_order(img.fwd_model);
0292 Sh= calc_system_mat( img );
0293 unit_test_cmp(['Linear ',str], Sh.E(1,1:4), tst, 1e-13)
0294 end
0295 end