0001 function fmdl = ng_mk_common_model(mdl_type, ...
0002 mdl_shape, elec_pos, elec_shape);
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 if ischar(mdl_type) && strcmp(mdl_type,'UNIT_TEST'); do_unit_test; return; end
0042
0043 if isstruct(mdl_type)
0044 error('No code yet to process options structs');
0045 else switch lower(mdl_type)
0046 case 'cyl'
0047 [body_geom, elec_geom, pp] = cyl_geom( mdl_shape, elec_pos, elec_shape);
0048 fmdl = ng_mk_geometric_models(body_geom, elec_geom);
0049 fmdl.body_geometry = body_geom;
0050 fmdl.electrode_geometry = elec_geom;
0051 case 'circ'
0052 [shape, elec_pos, elec_shape] = circ_geom( mdl_shape, elec_pos, elec_shape);
0053 fmdl = ng_mk_2d_model(shape, elec_pos, elec_shape);
0054 otherwise
0055 error('mdl_type = (%s) not available (yet)', mdl_type);
0056 end; end
0057
0058 if mdl_dim(fmdl)==3 && pp.is2D
0059 fmdl = mdl2d_from3d(fmdl);
0060 end
0061
0062
0063 function [shape, elec_pos, elec_shape] = circ_geom( mdl_shape, elec_pos, elec_shape);
0064 if mdl_shape(1) ~=0; error('specifying "circ" implies height of 0'); end
0065 if length(mdl_shape)==1
0066 rad = 1;
0067 maxh = 2*pi*1 / 16;
0068 elseif length(mdl_shape)==2
0069 rad = mdl_shape(2);
0070 maxh = 2*pi*rad / 16;
0071 else
0072 rad = mdl_shape(2);
0073 maxh= mdl_shape(3);
0074 end
0075
0076
0077 if size(elec_pos,1) == 0;
0078 theta= [];
0079 elseif size(elec_pos,1) == 1;
0080 theta = linspace( 0, 2*pi, elec_pos(1)+1)'; theta(end)=[];
0081 else
0082 theta = pi/180*elec_pos(:,1);
0083 end
0084
0085 elec_pos= rad*[sin(theta), cos(theta)];
0086
0087
0088 if length(elec_shape) == 1 && elec_shape(1) == 0
0089 elec_shape(2) = 10;
0090 end
0091
0092
0093
0094
0095
0096 theta_pts = ceil(2*pi*rad/maxh) - length(theta);
0097 if theta_pts > 0
0098 theta_ = [theta; 2*pi+theta(1)];
0099 per_interval = round( theta_pts * diff(theta_)/2/pi );
0100 for i=1:length(per_interval)
0101 new_pts = linspace( theta_(i), theta_(i+1), per_interval(i)+2);
0102 theta = [theta; new_pts(2:end-1)'];
0103 end
0104 theta = sort(theta);
0105
0106 end
0107
0108
0109 shape = {rad*[sin(theta),-cos(theta)], maxh};
0110
0111
0112 function [body_geom, elec_geom, pp] = cyl_geom( cyl_shape, elec_pos, elec_shape);
0113 [body_geom, pp] = parse_shape(cyl_shape);
0114 elec_geom = parse_elecs(elec_pos, elec_shape, pp);
0115
0116
0117 function [body_geom,pp] = parse_shape(cyl_shape);
0118 tank_height = cyl_shape(1);
0119 tank_radius = 1;
0120 tank_maxh = 0;
0121 is2D = 0;
0122
0123 if length(cyl_shape)>1;
0124 tank_radius=cyl_shape(2);
0125 end
0126 if length(cyl_shape)>2;
0127 tank_maxh =cyl_shape(3);
0128 end
0129 if tank_height==0;
0130 is2D = 1;
0131
0132
0133
0134 tank_height = tank_radius/5;
0135 if tank_maxh>0
0136 tank_height = min(tank_height,2*tank_maxh);
0137 end
0138 end
0139
0140 body_geom.cylinder.bottom_center = [0 0 0];
0141 body_geom.cylinder.top_center = [0 0 tank_height];
0142 body_geom.cylinder.radius = tank_radius;
0143 if tank_maxh > 0
0144 body_geom.max_edge_length = tank_maxh;
0145 end
0146
0147 pp.is2D = is2D;
0148 pp.tank_height= tank_height;
0149 pp.tank_radius= tank_radius;
0150 pp.body_geom = body_geom;
0151
0152
0153
0154
0155
0156
0157
0158
0159
0160
0161
0162
0163 function elecs= parse_elecs(elec_pos, elec_shape, pp)
0164 is2D = pp.is2D;
0165 elec_geom = struct([]);
0166 hig = pp.tank_height;
0167 rad = pp.tank_radius;
0168 body_geom = pp.body_geom;
0169
0170 n_elecs= size(elec_pos,1);
0171
0172 if n_elecs == 0
0173 elecs= {};
0174 return;
0175 end
0176
0177 if is2D
0178 elec_pos(:,2) = hig/2;
0179 end
0180
0181
0182
0183 if size(elec_pos,1) == 1
0184
0185 n_elecs= elec_pos(1);
0186 th = linspace(0,2*pi, n_elecs+1)'; th(end)=[];
0187
0188 on_elecs = ones(n_elecs, 1);
0189 el_th = [];
0190 el_z = [];
0191 if length(elec_pos) == 1;
0192 elec_pos(:,2) = hig/2;
0193 end
0194 for i=2:length(elec_pos)
0195 el_th = [el_th; th];
0196 el_z = [el_z ; on_elecs*elec_pos(i)];
0197 end
0198
0199 else
0200 el_th = elec_pos(:,1)*2*pi/360;
0201 el_z = elec_pos(:,2);
0202 end
0203
0204 n_elecs= size(el_z,1);
0205
0206 if size(elec_shape,1) == 1
0207 elec_shape = ones(n_elecs,1) * elec_shape;
0208 end
0209
0210 elecs= {};
0211 for i= 1:n_elecs
0212 row = elec_shape(i,:);
0213 elecs{i} = elec_spec( row, is2D, hig, rad, el_th(i), el_z(i) );
0214 end
0215
0216
0217
0218 function elec = elec_spec( row, is2D, hig, rad, el_th, el_z )
0219 xy_centre = rad*[sin(el_th),cos(el_th)];
0220 if is2D
0221 if row(1) == 0;
0222 elec.point = [xy_centre, 0];
0223 else
0224 el_z = hig/2;
0225 row(2)=hig;
0226 elec.intersection.cylinder(1).top_center = [0,0,2*row(1)];
0227 elec.intersection.cylinder(1).bottom_center = [0,0,-2*row(1)];
0228 elec.intersection.cylinder(1).radius = rad;
0229 elec.intersection.cylinder(1).complement_flag= 1;
0230 rad_dir = [sin(el_th);cos(el_th)];
0231 tan_dir = [0,1;-1,0]*rad_dir;
0232 elec.intersection.parallelepiped(1).vertex = [0.97*xy_centre' - row(1)/2*tan_dir; el_z - row(2)/2];
0233 elec.intersection.parallelepiped(1).vector_a = [0; 0; 1];
0234 elec.intersection.parallelepiped(1).vector_b = [rad_dir; 0];
0235 elec.intersection.parallelepiped(1).vector_c = [tan_dir; 0];
0236 elec.intersection.parallelepiped(2).vertex = [1.03*xy_centre' + row(1)/2*tan_dir; el_z + row(2)/2];
0237 elec.intersection.parallelepiped(2).vector_a =-[0; 0; 1];
0238 elec.intersection.parallelepiped(2).vector_b =-[rad_dir; 0];
0239 elec.intersection.parallelepiped(2).vector_c =-[tan_dir; 0];
0240
0241 elec.enter_body_flag = 0;
0242 end
0243 else
0244 if row(1) == 0
0245 elec.point = [xy_centre, el_z];
0246 elseif length(row)<2 || row(2) == 0
0247 elec.cylinder.top_center = [1.03*xy_centre, el_z];
0248 elec.cylinder.bottom_center = [0.97*xy_centre, el_z];
0249 elec.cylinder.radius = row(1);
0250 elec.enter_body_flag = 0;
0251 elseif row(2)>0
0252
0253
0254
0255
0256 rad_dir = [sin(el_th);cos(el_th)];
0257 tan_dir = [0,1;-1,0]*rad_dir;
0258 elec.intersection.parallelepiped(1).vertex = [0.97*xy_centre' - row(1)/2*tan_dir; el_z - row(2)/2];
0259 elec.intersection.parallelepiped(1).vector_a = [0; 0; 1];
0260 elec.intersection.parallelepiped(1).vector_b = [rad_dir; 0];
0261 elec.intersection.parallelepiped(1).vector_c = [tan_dir; 0];
0262 elec.intersection.parallelepiped(2).vertex = [1.03*xy_centre' + row(1)/2*tan_dir; el_z + row(2)/2];
0263 elec.intersection.parallelepiped(2).vector_a =-[0; 0; 1];
0264 elec.intersection.parallelepiped(2).vector_b =-[rad_dir; 0];
0265 elec.intersection.parallelepiped(2).vector_c =-[tan_dir; 0];
0266 else
0267 error('negative electrode width not supported');
0268 end
0269 end
0270
0271 if length(row)>=3 && row(3) > 0
0272 elec.max_edge_length = row(3);
0273 else
0274
0275 end
0276
0277
0278 function do_unit_test
0279 for tn = 1:do_test_number(0)
0280 fprintf('>>> ng_mk_cyl_models: TEST #%d\n',tn);
0281 fmdl= do_test_number(tn);
0282 subplot(3,3,rem(tn-1,9)+1)
0283 title(sprintf('test #%d',tn));
0284 show_fem(fmdl); drawnow
0285 end
0286
0287 function fmdl= do_test_number(tn)
0288 eidors_msg('ng_mk_cyl_models: UNIT_TEST #%d',tn,1);
0289 switch tn
0290 case 1;
0291
0292 fmdl= ng_mk_common_model('cyl',3,[0],[]);
0293
0294 case 2;
0295
0296 fmdl= ng_mk_common_model('cyl',[0,2,.2],[0],[]);
0297
0298 case 3;
0299
0300 fmdl= ng_mk_common_model('cyl',3,[8,1,2],[0.1]);
0301
0302 case 4;
0303
0304 fmdl= ng_mk_common_model('cyl',3,[7,1],[0.2,0,0.05]);
0305
0306 case 5;
0307
0308 fmdl= ng_mk_common_model('cyl',3,[7,1],[0.2,0.3]);
0309
0310 case 6;
0311
0312 fmdl= ng_mk_common_model('cyl',0,[11],[0.2,0,0.05]);
0313
0314 case 7;
0315
0316 fmdl= ng_mk_common_model('cyl',[0,1,0.1],[11],[0.2,0,0.02]);
0317
0318 case 8;
0319
0320 fmdl= ng_mk_common_model('cyl',0,[0;90;120],[0.2,0,0.03]);
0321
0322 case 9;
0323
0324 fmdl= ng_mk_common_model('cyl',0,[0;120],[0.4,0,0.01;0.1,0,0.1]);
0325
0326 case 10;
0327
0328 fmdl= ng_mk_common_model('cyl',3,[0,0.5;30,1;60,1.5;90,2.0],[0.2,0,0.1]);
0329
0330 case 11;
0331
0332 el_pos = [0,0.5;30,1;60,1.5;90,2.0];
0333 el_sz = [0.2,0,0.1;0.1,0,0.05;0.2,0.2,0.02;0.2,0.4,0.5];
0334 fmdl= ng_mk_common_model('cyl',3,el_pos,el_sz);
0335
0336
0337 case 12;
0338 fmdl = ng_mk_common_model('circ', [0,1,.1], [4], [0.4,10]);
0339 case 13;
0340 fmdl = ng_mk_common_model('circ', 0, [9], [0.2,3]);
0341 case 14;
0342 fmdl = ng_mk_common_model('circ',[0,1,.10], [9], [0,1]);
0343 case 15;
0344 fmdl = ng_mk_common_model('circ',[0,1,.10], [9], [0]);
0345 case 16;
0346 fmdl = ng_mk_common_model('circ',[0,2,.05], [9], [0.1,100]);
0347
0348 case 0; fmdl = 16;
0349 otherwise;
0350 error('huh?')
0351 end
0352
0353 if exist('img'); fmdl = img; end