0001 function param= mk_circ_tank(rings, levels, elec_spec );
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
0040
0041
0042
0043
0044
0045 if rem(rings,4) ~= 0
0046 error('parameter rings and must be divisible by 4');
0047 end
0048
0049
0050 n_elec= [];
0051 if size(elec_spec) == [1,1] if isnumeric(elec_spec)
0052 n_elec= elec_spec;
0053 end; end
0054
0055 [elem, node, bdy, point_elec_nodes, node_order] = mk_2D_model( rings );
0056
0057 if isempty( levels )
0058
0059 if ~isempty( n_elec )
0060 idx= (0:n_elec-1)*length(point_elec_nodes)/n_elec + 1;
0061 if any(rem(idx,1) ~= 0);
0062 error('The requested number of electrodes is not compatible with this FEM mesh')
0063 end
0064 elec_nodes= point_elec_nodes( idx );
0065 else
0066 error('2D models only support scalar electrode patterns');
0067 end
0068 else
0069 [elem, node, bdy, point_elec_nodes] = mk_3D_model( elem, node, ...
0070 levels, bdy, point_elec_nodes, node_order );
0071
0072
0073
0074 if ~isempty( n_elec )
0075 idx= (0:n_elec-1)*length(point_elec_nodes)/n_elec + 1;
0076 half_lev = ceil( length(levels)/2 );
0077 elec_nodes= point_elec_nodes( half_lev, idx );
0078 else
0079 elec_nodes= electrode_pattern( point_elec_nodes, elec_spec );
0080 end
0081
0082 end
0083
0084 param.name= sprintf('EIT FEM by mk_circ_tank with N=%d levs=%d', ...
0085 rings, length(levels) );
0086 param.nodes = node';
0087 param.elems = elem';
0088 param.boundary = bdy';
0089 param.gnd_node = 1;
0090 param.electrode = mk_electrodes( elec_nodes );
0091
0092 return;
0093
0094
0095
0096
0097
0098
0099
0100
0101
0102
0103 function elec_nodes= electrode_pattern( point_elec_nodes, elec_spec )
0104 elec_nodes= [];
0105 lpe = size(point_elec_nodes,2);
0106 nlev= size(point_elec_nodes,1);
0107 for i=1:3:length(elec_spec)-2
0108 spec = elec_spec{i};
0109 if strcmp( spec,'planes' )
0110 n_elec= elec_spec{i+1};
0111 levs = elec_spec{i+2};
0112
0113 eidx= (0:n_elec-1);
0114 idx= round(eidx*lpe/n_elec) + 1;
0115 nodes= point_elec_nodes( levs, idx )';
0116 elec_nodes= [ elec_nodes; nodes(:) ];
0117 elseif strcmp( spec,'zigzag' )
0118 n_elec= elec_spec{i+1};
0119 levs = elec_spec{i+2};
0120 if any(levs > size(point_elec_nodes,1))
0121 error('requested electrode plane larger than FEModel');
0122 end
0123
0124 eidx= (0:n_elec-1);
0125 idx= round(eidx*lpe/n_elec)*nlev + ...
0126 levs( rem( eidx, length(levs))+1);
0127 nodes= point_elec_nodes( idx );
0128 elec_nodes= [ elec_nodes; nodes(:) ];
0129 else
0130 error('elec_spec parameter not understood');
0131 end
0132 end
0133
0134
0135
0136 function [ELEM, NODE, bdy_nodes, point_elec_nodes, NODE_order] = ...
0137 mk_2D_model( N );
0138 ELEM=[];
0139 NODE= [0;0];
0140 NODE_order= [1];
0141 int=1;
0142 for k=1:N
0143 phi= (0:4*k-1)*pi/2/k;
0144 NODE= [NODE k/N*[sin(phi);cos(phi)]];
0145
0146
0147
0148 NOq= rem(k+(0:k),3)+1;
0149 NODE_order= [NODE_order, NOq([1:k, k+1:-1:2, 1:k, k+1:-1:2])];
0150
0151 ext= 2*(k*k-k+1);
0152 idxe=[0:k-1; 1:k];
0153 idxi=[0:k-1];
0154 elem= [ ext+idxe, ext+2*k+[-idxe idxe], ...
0155 ext+rem(4*k-idxe,4*k), ...
0156 ext+idxe, ext+2*k+[-idxe idxe], ...
0157 ext+rem(4*k-idxe,4*k);
0158 int+idxi, int+2*(k-1)+[-idxi, idxi], ...
0159 int+rem(4*(k-1)-idxi, 4*(k-1)+(k==1) ) ...
0160 ext+4*k+1+idxi, ...
0161 ext+6*k+ [1-idxi 3+idxi], ...
0162 ext+8*k+3-idxi ];
0163 for j=1:k
0164 r1= rem(j+k-1,3)+1;
0165 r2= rem(j+k,3)+1;
0166 r3= 6-r1-r2;
0167 elem([r1 r2 r3],j+k*(0:7) )= elem(:,j+k*(0:7));
0168 end
0169
0170 ELEM=[ ELEM elem(:,1:(8-4*(k==N))*k) ];
0171 int=ext;
0172 end
0173
0174 bdy_nodes= [ (ext :ext+N*4-1) ; ...
0175 (ext+1:ext+N*4-1), ext ];
0176 point_elec_nodes= (ext):(ext+N*4-1) ;
0177
0178
0179
0180
0181
0182
0183
0184
0185 function [ELEM, NODE, BDY, elec_nodes] = mk_3D_model( ...
0186 elem0, node0, niveaux, bdy, elec_nodes0, node_order );
0187
0188 elem0= node_reorder( elem0, node_order);
0189
0190 d= size(elem0,1);
0191 n= size(node0,2);
0192 e= size(elem0,2);
0193
0194
0195 elem_odd= [elem0([3,2,1,1],:), ...
0196 elem0([3,2,2,1],:), ...
0197 elem0([3,3,2,1],:)];
0198 elem_even=[elem0([1,2,3,3],:), ...
0199 elem0([1,2,2,3],:), ...
0200 elem0([1,1,2,3],:)];
0201
0202 NODE= [node0; niveaux(1)*ones(1,n) ];
0203 ELEM= [];
0204 bl= size(bdy,2);
0205
0206
0207 bdy_order =node_order(bdy);
0208 bdy_up= find(bdy_order>[1;1]*min(bdy_order));
0209 bdy_dn= find(bdy_order<[1;1]*max(bdy_order));
0210
0211 bdy_odd = [bdy; bdy(bdy_up')];
0212 bdy_even= [bdy; bdy(bdy_dn')];
0213 BDY = [];
0214
0215 ln= length(niveaux);
0216 for k=2:ln
0217 NODE=[NODE [node0; niveaux(k)*ones(1,n)] ];
0218 if rem(k,2)==1
0219 elem= elem_odd;
0220 bdy_e0= bdy_even;
0221 bdy_e1= bdy_odd;
0222 else
0223 elem= elem_even;
0224 bdy_e1= bdy_even;
0225 bdy_e0= bdy_odd;
0226 end
0227 el_add = (k-2)*n+[[zeros(3,e);n*ones(1,e)], ...
0228 [zeros(2,e);n*ones(2,e)], ...
0229 [zeros(1,e);n*ones(3,e)]];
0230 ELEM= [ELEM,elem + el_add];
0231 BDY= [BDY, bdy_e0+(k-2)*n+[zeros(2,bl);n*ones(1,bl)], ...
0232 bdy_e1+(k-2)*n+[n*ones(2,bl);zeros(1,bl)] ];
0233 end
0234
0235
0236 BDY= [elem0, BDY, elem0+n*(ln-1) ];
0237
0238
0239 elec_nodes= ones(ln,1) * elec_nodes0 + ...
0240 (0:ln-1)' * n*ones(1, length(elec_nodes0) );
0241
0242
0243
0244
0245
0246
0247 function elec_struct = mk_electrodes( elec_nodes)
0248 for i= 1:length( elec_nodes )
0249 elec_struct(i).nodes = elec_nodes(i);
0250 elec_struct(i).z_contact = 0.001;
0251 end
0252
0253 if ~exist('elec_struct');
0254 elec_struct= [];
0255 end
0256
0257 function elem= node_reorder( elem0, node_order);
0258 e= size(elem0,2);
0259
0260 no_test= node_order(elem0);
0261 no_test= (0:e-1)'*[3,3,3]+no_test';
0262 elem= elem0(no_test');
0263
0264 no_test = node_order(elem);
0265 ok= ~norm(no_test - [1;2;3]*ones(1,e));
0266
0267 if ~ok; error('test_node_order fails - cant do 3D meshes'); end