21 i.KeepUnmatched=
true;
22 i.addParamValue(
'Radius',1);
23 i.addParamValue(
'InnerRadius',.5);
24 i.addParamValue(
'Gamma',2);
25 i.addParamValue(
'Layers',1);
26 i.addParamValue(
'MinZ',[]);
36 x = linspace(len(1),len(2),parts*2+1);
38 x = linspace(0,len,parts*2+1);
40 if isa(opt.Radius,
" function_handle ")
46 if isscalar(opt.Gamma)
47 opt.Gamma= [opt.Gamma opt.Gamma];
49 if isscalar(opt.Radius)
50 opt.Radius= [opt.Radius opt.Radius];
52 k = kernels.GaussKernel;
53 k.Gamma= opt.Gamma(1);
54 fx(1,:) = k.evaluate(x,len/2)^
t*opt.Radius(1);
55 k.Gamma= opt.Gamma(2);
56 fx(2,:) = k.evaluate(x,len/2)^
t*opt.Radius(2);
58 if isscalar(opt.InnerRadius)
59 opt.InnerRadius= [1 1]*opt.InnerRadius;
62 posfun = @(omega,offset)[sin(omega+offset); cos(omega+offset)];
64 qpart = getQuarterPart(opt.Layers);
65 baseelems = zeros(size(qpart,1),size(qpart,2),4);
66 baseelems(:,:,1) = qpart;
67 nelems = size(baseelems,1)/2;
70 baseelems(pos,:,2) = [-1 0; 0 1]*baseelems(pos,[3 2 1 6 5 4 9 8 7],1);
72 baseelems(:,:,3) = -baseelems(:,9:-1:1,1);
73 baseelems(:,:,4) = -baseelems(:,9:-1:1,2);
86 npp = 27*parts*nelems;
87 nodes = zeros(3,npp*4);
89 elempos = (p-1)*2 + (1:3);
90 rx = ones(9,1) * (opt.InnerRadius(1) + fx(1,elempos));
91 ry = ones(9,1) * (opt.InnerRadius(2) + fx(2,elempos));
92 z = ones(9,1) * x(elempos);
94 elem = baseelems((1:2)+2*(k-1),:,:);
96 nodepos = (((p-1) * nelems + (k-1))*4 + (rotpart-1))*27 + (1:27);
97 nodes(1,nodepos) = bsxfun(@times,repmat(elem(1,:,rotpart),1,3),rx(:)^
t);
98 nodes(2,nodepos) = bsxfun(@times,repmat(elem(2,:,rotpart),1,3),ry(:)^
t);
99 nodes(3,nodepos) = z(:);
105 [nodes, ~, elems] = unique(nodes
" , "rows
" , "stable^
t);
109 [D, idx] = sort(D,
" ascend ");
110 same = D < eps*max(D);
111 [i,j] = find(tril(ones(size(nodes,1)),-1));
112 i = i(idx(same)); j = j(idx(same));
118 elems(elems == j(k)) = i(k);
121 effidx = unique(elems(:));
123 invidx(effidx) = 1:length(effidx);
125 elems = invidx(elems);
129 elems = reshape(elems,27,[])^
t;
138 if ~isempty(opt.MinZ)
140 hlp_g27 = fem.geometry.Cube27Node;
141 centerline_facenodeidx = hlp_g27.MasterFaces(3,:);
142 for elem = [3:4:4*parts 4:4:4*parts]
143 centerline_nodes = elems(elem,centerline_facenodeidx);
144 toScale = nodes(2,centerline_nodes) < opt.MinZ;
145 factor = opt.MinZ./nodes(2,centerline_nodes(toScale));
146 nodes(2,centerline_nodes(toScale)) = opt.MinZ;
148 inner_nodes = elems(elem,[4:6 13:15 22:24]);
149 nodes(2,inner_nodes(toScale)) = nodes(2,inner_nodes(toScale)).*factor;
153 geo27 = fem.geometry.Cube27Node(nodes,elems);
156 function elems = getQuarterPart(elem_layers)
160 if isscalar(elem_layers)
161 elem_layers = linspace(0,1,elem_layers+1);
162 elem_layers = elem_layers(2:end);
164 elem_layers = elem_layers / max(elem_layers);
165 num_elem_layers = length(elem_layers);
168 if mod(num_elem_layers,2) == 1
169 elem_layers(end+1) = elem_layers(end)*1.1;
173 o = posfun(linspace(0,pi/2,5),0);
174 c = posfun(pi/4,0)/2;
175 elems(1:2,:) = [0 .5 1 0 c(1) o(1,4) o(1,1:3)
176 0 0 0 .5 c(2) o(2,4) o(2,1:3)]*elem_layers(1);
178 if num_elem_layers > 1
179 o = elem_layers(2)*posfun(linspace(0,pi/2,5),0);
180 elems(3:4,:) = [elems(1:2,7:9) (o(:,1:3)+elems(1:2,7:9))/2 o(:,1:3)];
181 elems(5:6,:) = [elems(1:2,[9 6 3]) (o(:,3:5)+elems(1:2,[9 6 3]))/2 o(:,3:5)];
183 elems(5:6,:) = elems(5:6,[3 6 9 2 5 8 1 4 7]);
187 num_block_layers = ceil(num_elem_layers/2)-1;
191 for bn=1:num_block_layers
192 layerpos = (2:4)+2*(bn-1);
193 for b = 1:blocks_per_loop
195 new = getblock(elem_layers(layerpos),omega,off);
196 if bn == num_block_layers && mod(num_elem_layers,2) ~= 0
200 elems(end+1:end+size(
new,1),:) =
new;
203 blocks_per_loop = blocks_per_loop*2;
207 function elems = getblock(radii,omega,offset)
208 i = radii(1)*posfun(linspace(0,omega,5),offset);
209 m = radii(2)*posfun(linspace(0,omega,13),offset);
210 m = m(:,[1 3 5:9 11 13]);
211 o = radii(3)*posfun(linspace(0,omega,9),offset);
214 elems(1:2,:) = [i(:,1:3) (m(:,1:3)+i(:,1:3))/2 m(:,1:3)];
216 elems(5:6,:) = [i(:,3:5) (m(:,7:9)+i(:,3:5))/2 m(:,7:9)];
217 center = (radii(1)+radii(2))/2*posfun(omega/2,offset);
219 elems(3:4,:) = [elems(5:6,[1 4 7]) elems(1:2,6) center m(:,[6 3:5])];
222 elems(7:8,:) = [elems(1:2,7:9) (o(:,1:3)+elems(1:2,7:9))/2 o(:,1:3)];
223 elems(9:10,:) = [elems(3:4,7:9) (o(:,3:5)+elems(3:4,7:9))/2 o(:,3:5)];
224 elems(11:12,:) = [elems(3:4,[9 6 3]) (o(:,5:7)+elems(3:4,[9 6 3]))/2 o(:,5:7)];
225 elems(13:14,:) = [elems(5:6,7:9) (o(:,7:9)+elems(5:6,7:9))/2 o(:,7:9)];
function geo27 = Belly(parts, len, varargin)
Code to generate a belly-shaped geometry with various options.
A variable number of input arguments.