You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

222 lines
7.4 KiB

%--------------------------
% @Author: Jingqiao Hu
% @Date: 2021-11-02 15:18:36
% @LastEditTime: 2021-11-04 15:56:57
% Ke is [6,6,faces_num]
%--------------------------
function optimize_t_trimesh(Ke, nodes, faces, nodes_cell, faces_cell, MMCs, MMCs_max, MMCs_min, radius, p, ...
edofMat, iK, jK, freedofs, F, nidx_cell, fidx_cell, MMCs_num, volfrac)
nele_global = size(faces, 1);
cvt_num = size(MMCs, 1);
pn = 16; % for pnorm
U = zeros(size(nodes,1)*2, 1);
[xval, xold1, xold2, xmin, xmax, low, upp, m_mma, c_mma, d_mma, a0_mma, a_mma] = MMA_paras1(MMCs, MMCs_min, MMCs_max, MMCs_num);
loop = 1; change = 1; maxloop = 100;
while loop < maxloop && change > 1e-4
%% MMC-part
[H, dH_global, denk_global, den_global, v_local] = project_MMC(nodes_cell, faces_cell, MMCs, radius, p, nidx_cell, fidx_cell);
figure(1); clf; trisurf(faces, nodes(:,1), nodes(:,2), H);
%% simulation
[dcdH, comp] = simulation_MMC_trimesh(edofMat, iK, jK, freedofs, U, F, Ke, denk_global, den_global);
cons_v_micro = (mean(v_local.^pn))^(1/pn);
%% Sensitivities
dpnorm = 1/cvt_num * (mean(v_local.^pn))^(1/pn-1) * (v_local.^(pn-1)); % [cvy_num,1]
dpn_expand = zeros(nele_global, 1);
for i = 1 : cvt_num
dpn_expand(fidx_cell(i,1) : fidx_cell(i,2)) = dpnorm(i);
end
dvdH = ones(nele_global, 1) / nele_global .* dpn_expand;
dc = zeros(MMCs_num, 3);
dv = zeros(MMCs_num, 3);
idx = 0;
for i = 1 : cvt_num
% NOTE: each MMC only effects its own cell
dH = dH_global{i};
edges_num = size(MMCs{i}, 2);
dcdt = zeros(edges_num, 3);
dvdt = zeros(edges_num, 3);
for e = 1 : edges_num
dHdt = squeeze(dH(e, :, :))'; % [m,3]
dcdt(e, :) = dcdH(:)' * dHdt; % [1,m]*[m,3] -> [1,3]
dvdt(e, :) = dvdH(:)' * dHdt;
end
dc(idx+1 : idx+edges_num, :) = dcdt;
dv(idx+1 : idx+edges_num, :) = dvdt;
end
dc = dc'; % change to [3, MMCs_num]
dv = dv';
%% optimization-part
f0val= comp;
df0dx= -dc(:) / max(abs(dc(:)));
fval = cons_v_micro - volfrac;
dfdx = dv(:) / max(abs(dv(:)));
[xmma, ~, ~, ~, ~, ~, ~, ~, ~,low, upp]= mmasub_mmc(m_mma, nn, Loop, xval(:), xmin, xmax, xold1,...
xold2, f0val, df0dx, fval, dfdx', low, upp, a0_mma, a_mma, c_mma, d_mma);
xold2 = xold1; xold1 = xval;
change = max(abs(xval-xmma));
% update MMCs
MMCs = update_MMC(xval, MMCs);
end
end
%% utils
function [dcdH, comp] = simulation_MMC_trimesh(edofMat, iK, jK, freedofs, U, F, Ke, denk, den)
sKe = reshape(Ke, 36, []); % [36,m]
sK = sKe .* denk(:)';
K = sparse(iK(:),jK(:),sK(:)); K=(K+K')/2;
U(freedofs,:) = K(freedofs,freedofs) \ F(freedofs,:);
% Energy of element
u0 = U(edofMat)'; % [6,m]
u1(1,:,:) = u0; % [1,6,m]
u2(:,1,:) = u0; % [6,1,m]
energy = squeeze(mtimesx(mtimesx(u1, Ke), u2)); % [m,1]
dcdH = 2 * energy(:) .* den(:); % [m,1]
comp = F'*U;
end
function [H_global, dH_global, denk_global, den_global, v_local] = project_MMC(nodes_cell, faces_cell, MMCs, radius, p, nidx_cell, fidx_cell)
cvt_num = size(MMCs, 1);
denk_global = zeros(fidx_cell(end), 1);
den_global = zeros(fidx_cell(end), 1);
v_local = zeros(cvt_num, 1); % for volume-pnorm
H_global = zeros(nidx_cell(end), 1);
dH_global = cell(cvt_num, 1);
step = radius / 2;
for i = 1:cvt_num
mmc = MMCs{i}; % [7, edges_num]
nodes = nodes_cell{i};
faces = faces_cell{i};
edges_num = size(mmc,2); % edges_num
each_phi = cell(edges_num, 1);
phi0 = 0;
for j = 1 : edges_num
tmpPhi = tPhi(mmc(:,j), nodes(:,1), nodes(:,2));
each_phi{j} = tmpPhi;
phi0 = phi0 + exp(p * tmpPhi);
end
phi_max = log(phi0) / p;
H = Heaviside_simply(phi_max, radius);
H_global(nidx_cell(i,1) : nidx_cell(i,2)) = H;
edofMat0 = [2*faces-1, 2*faces]; % [n,6]
edofMat = edofMat0(:, [1,4,2,5,3,6]);
EleNodesID = edofMat(:, 2:2:6) ./ 2;
denk= sum(H(EleNodesID).^2, 2) / 3; % 3 for tiangle
den = sum(H(EleNodesID), 2) / 3; % [m,1]
denk_global(fidx_cell(i,1) : fidx_cell(i,2)) = denk;
den_global(fidx_cell(i,1) : fidx_cell(i,2)) = den;
v_local(i) = mean(den);
% figure(3); clf; trimesh(faces, nodes(:,1), nodes(:,2), H);
faces_num = size(faces, 1);
dH_global{i} = sensitivity_MMC(edges_num, mmc, step, nodes, p, each_phi, radius, EleNodesID, faces_num);
end
end
function dH = sensitivity_MMC(edges_num, mmc, step, nodes, p, each_phi, radius, EleNodesID, faces_num)
dH = zeros(edges_num, 3, faces_num);
for j = 1 : edges_num
mmc_j = mmc(:,j);
for ti = 1 : 3
mmc_plus = mmc_j;
mmc_minus = mmc_j;
mmc_plus(ti) = mmc_j(ti) + step;
phi_plus0 = tPhi(mmc_plus, nodes(:,1), nodes(:,2));
phi_plus = exp(p * phi_plus0);
for j1 = 1 : j-1
phi_plus = phi_plus + exp(p * each_phi{j1});
end
for j2 = j+1 : edges_num
phi_plus = phi_plus + exp(p * each_phi{j2});
end
phi_plus_blend = log(phi_plus) / p;
mmc_minus(ti) = mmc_j(ti) - step;
phi_minus0 = tPhi(mmc_minus, nodes(:,1), nodes(:,2));
phi_minus = exp(p * phi_minus0);
for j1 = 1 : j-1
phi_minus = phi_minus + exp(p * each_phi{j1});
end
for j2 = j+1 : edges_num
phi_minus = phi_minus + exp(p * each_phi{j2});
end
phi_minus_blend = log(phi_minus) / p;
H_plus = Heaviside_simply(phi_plus_blend, radius);
H_minus = Heaviside_simply(phi_minus_blend, radius);
dHi = (H_plus - H_minus) / (2 * step); % [n,1]
dH(j, ti, :) = sum(dHi(EleNodesID), 2) / 3; % [n,1] -> [m,1]
% CHECK: need dH/dH_e ? from node to ele
% figure(1); clf; trimesh(faces, nodes(:,1), nodes(:,2), H_plus);
% figure(2); clf; trimesh(faces, nodes(:,1), nodes(:,2), H_minus);
end
end
end
function MMCs = update_MMC(xval, MMCs)
cvt_num = size(MMCs, 1);
idx = 0;
for i = 1:cvt_num
mmc = MMCs{i};
edges_num = size(mmc, 2);
MMCs{i}(1:3, :) = xval(:, idx+1 : idx+edges_num);
end
end
function [xval, xold1, xold2, xmin, xmax, low, upp, m_mma, c_mma, d_mma, a0_mma, a_mma] = MMA_paras1(MMCs, MMCs_min, MMCs_max, MMCs_num)
xval = zeros(3, MMCs_num);
xmin = zeros(3, MMCs_num);
xmax = zeros(3, MMCs_num);
cvt_num = size(MMCs, 1);
idx = 0;
for i = 1 : cvt_num
mmc = MMCs{i};
edges_num = size(mmc, 2);
xval(:, idx+1 : idx+edges_num) = mmc(1:3, :);
xmin(:, idx+1 : idx+edges_num) = MMCs_min{i}(1:3, :);
xmax(:, idx+1 : idx+edges_num) = MMCs_max{i}(1:3, :);
end
% variables are t1,t2,t3
xval = xval(:);
xold1= xval; xold2 = xval;
xmin = xmin(:); xmax = xmax(:);
low = xmin; upp = xmax;
m_mma = 1; % number of constrainm
c_mma = 1000*ones(m_mma,1); d_mma = zeros(m_mma,1); a0_mma = 1; a_mma = zeros(m_mma,1);
end