-
Amira Abdel-Rahman authoredAmira Abdel-Rahman authored
concurrent3d.jl 18.56 KiB
# Amira Abdel-Rahman
# (c) Massachusetts Institute of Technology 2020
function ConTop3D(Macro_struct, Micro_struct, penal, rmin)
# USER-DEFINED LOOP PARAMETERS
maxloop = 200; displayflag = 1; E0 = 1; Emin = 1e-9; nu = 0.3;
Macro_length = Macro_struct[1]; Macro_width = Macro_struct[2]; Macro_Height = Macro_struct[3];
Micro_length = Micro_struct[1]; Micro_width = Micro_struct[2]; Micro_Height = Micro_struct[3];
Macro_nelx = Macro_struct[4]; Macro_nely = Macro_struct[5]; Macro_nelz = Macro_struct[6];
Micro_nelx = Micro_struct[4]; Micro_nely = Micro_struct[5]; Micro_nelz = Micro_struct[6];
Macro_Vol = Macro_struct[7]; Micro_Vol = Micro_struct[7];
Macro_Elex = Macro_length/Macro_nelx; Macro_Eley = Macro_width/Macro_nely; Macro_Elez = Macro_Height/Macro_nelz;
Macro_nele = Macro_nelx*Macro_nely*Macro_nelz; Micro_nele = Micro_nelx*Micro_nely*Micro_nelz;
Macro_ndof = 3*(Macro_nelx+1)*(Macro_nely+1)*(Macro_nelz+1);
# PREPARE FINITE ELEMENT ANALYSIS
[load_x,load_y,load_z] = meshgrid(Macro_nelx/2, Macro_nely, Macro_nelz/2);
loadnid = load_z*(Macro_nelx+1)*(Macro_nely+1)+load_x*(Macro_nely+1)+(Macro_nely+1-load_y);
F = sparse(3*loadnid[:] - 1,1,-1,Macro_ndof,1);
U = zeros(Macro_ndof,1);
[fixed_x,fixed_y,fixed_z] = meshgrid( [0 Macro_nelx],0,[0 Macro_nelz] );
fixednid = fixed_z*(Macro_nelx+1)*(Macro_nely+1)+fixed_x*(Macro_nely+1)+(Macro_nely+1-fixed_y);
fixeddofs = [3*fixednid[:]; 3*fixednid[:]-1; 3*fixednid[:]-2];
freedofs = setdiff(1:Macro_ndof,fixeddofs);
nodegrd = reshape(1:(Macro_nely+1)*(Macro_nelx+1),Macro_nely+1,Macro_nelx+1);
nodeids = reshape(nodegrd[1:end-1,1:end-1],Macro_nely*Macro_nelx,1);
nodeidz = 0:(Macro_nely+1)*(Macro_nelx+1):(Macro_nelz-1)*(Macro_nely+1)*(Macro_nelx+1);
nodeids = repmat(nodeids,size(nodeidz))+repmat(nodeidz,size(nodeids));
edofMat = repmat(3*nodeids[:]+1,1,24)+ repmat( [0 1 2 3*Macro_nely + [3 4 5 0 1 2] -3 -2 -1
3*(Macro_nely+1)*(Macro_nelx+1)+[0 1 2 3*Macro_nely + [3 4 5 0 1 2] -3 -2 -1]],Macro_nele,1);
iK = reshape(kron(edofMat,ones(24,1))',24*24*Macro_nele,1);
jK = reshape(kron(edofMat,ones(1,24))',24*24*Macro_nele,1);
# PREPARE FILTER
Macro_H,Macro_Hs = filtering3d(Macro_nelx, Macro_nely, Macro_nelz, Macro_nele, rmin);
Micro_H,Micro_Hs = filtering3d(Micro_nelx, Micro_nely, Micro_nelz, Micro_nele, rmin);
# INITIALIZE ITERATION
Macro_x = repmat(Macro_Vol,[Macro_nely,Macro_nelx,Macro_nelz] );
Micro_x = ones(Micro_nely,Micro_nelx,Micro_nelz);
Micro_x[Micro_nely/2:Micro_nely/2+1,Micro_nelx/2:Micro_nelx/2+1,Micro_nelz/2:Micro_nelz/2+1] = 0;
beta = 1;
Macro_xTilde = Macro_x; Micro_xTilde = Micro_x;
Macro_xPhys = 1-exp(-beta*Macro_xTilde)+Macro_xTilde*exp(-beta);
Micro_xPhys = 1-exp(-beta*Micro_xTilde)+Micro_xTilde*exp(-beta);
loopbeta = 0; loop = 0; Macro_change = 1; Micro_change = 1;
while loop < maxloop || Macro_change > 0.01 || Micro_change > 0.01
loop = loop+1; loopbeta = loopbeta+1;
# FE-ANALYSIS AT TWO SCALES
DH, dDH = EBHM3D(Micro_xPhys, Micro_length, Micro_width, Micro_Height, E0, Emin, nu, penal);
Ke = elementMatVec3D(Macro_Elex/2, Macro_Eley/2, Macro_Elez/2, DH);
sK = reshape(Ke[:]*(Emin+Macro_xPhys[:]'.^penal*(1-Emin)),24*24*Macro_nele,1);
K = sparse(iK,jK,sK); K = (K+K')/2;
U[freedofs,:] = K[freedofs,freedofs]\F[freedofs,:];
# OBJECTIVE FUNCTION AND SENSITIVITY ANALYSIS
ce = reshape(sum((U[edofMat]*Ke).*U[edofMat],2),[Macro_nely,Macro_nelx,Macro_nelz] );
c = sum(sum(sum((Emin+Macro_xPhys.^penal*(1-Emin)).*ce)));
Macro_dc = -penal*(1-Emin)*Macro_xPhys.^(penal-1).*ce;
Macro_dv = ones(Macro_nely, Macro_nelx, Macro_nelz);
Micro_dc = zeros(Micro_nely, Micro_nelx, Micro_nelz);
for i = 1:Micro_nele
dDHe = [dDH[1,1][i] dDH[1,2][i] dDH[1,3][i] dDH[1,4][i] dDH[1,5][i] dDH[1,6][i];
dDH[2,1][i] dDH[2,2][i] dDH[2,3][i] dDH[2,4][i] dDH[2,5][i] dDH[2,6][i];
dDH[3,1][i] dDH[3,2][i] dDH[3,3][i] dDH[3,4][i] dDH[3,5][i] dDH[3,6][i];
dDH[4,1][i] dDH[4,2][i] dDH[4,3][i] dDH[4,4][i] dDH[4,5][i] dDH[4,6][i];
dDH[5,1][i] dDH[5,2][i] dDH[5,3][i] dDH[5,4][i] dDH[5,5][i] dDH[5,6][i];
dDH[6,1][i] dDH[6,2][i] dDH[6,3][i] dDH[6,4][i] dDH[6,5][i] dDH[6,6][i]];
dKE = elementMatVec3D(Macro_Elex, Macro_Eley, Macro_Elez, dDHe);
dce = reshape(sum((U[edofMat]*dKE).*U[edofMat],2),[Macro_nely,Macro_nelx,Macro_nelz] );
Micro_dc[i] = -sum(sum(sum((Emin+Macro_xPhys.^penal*(1-Emin)).*dce)));
end
Micro_dv = ones(Micro_nely, Micro_nelx, Micro_nelz);
# FILTERING AND MODIFICATION OF SENSITIVITIES
Macro_dx = beta*exp(-beta*Macro_xTilde)+exp(-beta); Micro_dx = beta*exp(-beta*Micro_xTilde)+exp(-beta);
Macro_dc[:] = Macro_H*(Macro_dc[:].*Macro_dx[:]./Macro_Hs); Macro_dv[:] = Macro_H*(Macro_dv[:].*Macro_dx[:]./Macro_Hs);
Micro_dc[:] = Micro_H*(Micro_dc[:].*Micro_dx[:]./Micro_Hs); Micro_dv[:] = Micro_H*(Micro_dv[:].*Micro_dx[:]./Micro_Hs);
# OPTIMALITY CRITERIA UPDATE MACRO AND MICRO ELELMENT DENSITIES
Macro_x, Macro_xPhys, Macro_change = OC(Macro_x, Macro_dc, Macro_dv, Macro_H, Macro_Hs, Macro_Vol, Macro_nele, 0.02, beta);
Micro_x, Micro_xPhys, Micro_change = OC(Micro_x, Micro_dc, Micro_dv, Micro_H, Micro_Hs, Micro_Vol, Micro_nele, 0.02, beta);
Macro_xPhys = reshape(Macro_xPhys, Macro_nely, Macro_nelx, Macro_nelz);
Micro_xPhys = reshape(Micro_xPhys, Micro_nely, Micro_nelx, Micro_nelz);
# PRINT RESULTS
# display(' It.:#5i Obj.:#11.4f Macro_Vol.:#7.3f Micro_Vol.:#7.3f Macro_ch.:#7.3f Micro_ch.:#7.3f\n', loop,c,mean(Macro_xPhys[:] ),mean(Micro_xPhys[:] ), Macro_change, Micro_change);
# if displayflag, clf; display_3D(Macro_xPhys); end
# if displayflag, clf; display_3D(Micro_xPhys); end
# UPDATE HEAVISIDE REGULARIZATION PARAMETER
if beta < 512 && (loopbeta >= 50 || Macro_change <= 0.01 || Micro_change <= 0.01 )
beta = 2*beta; loopbeta = 0; Macro_change = 1; Micro_change = 1;
display("Parameter beta increased to $beta.");
end
end
end
## SUB FUNCTION:filtering3D
function filtering3d(nelx, nely, nelz, nele, rmin)
iH = ones(nele*(2*(ceil(rmin)-1)+1)^2,1);
jH = ones(size(iH));
sH = zeros(size(iH));
k = 0;
for k1 = 1:nelz
for i1 = 1:nelx
for j1 = 1:nely
e1 = (k1-1)*nelx*nely + (i1-1)*nely+j1;
for k2 = max(k1-(ceil(rmin)-1),1):min(k1+(ceil(rmin)-1),nelz)
for i2 = max(i1-(ceil(rmin)-1),1):min(i1+(ceil(rmin)-1),nelx)
for j2 = max(j1-(ceil(rmin)-1),1):min(j1+(ceil(rmin)-1),nely)
e2 = (k2-1)*nelx*nely + (i2-1)*nely+j2;
k = k+1;
iH[k] = e1;
jH[k] = e2;
sH[k] = max(0,rmin-sqrt((i1-i2)^2+(j1-j2)^2+(k1-k2)^2));
end
end
end
end
end
end
H = sparse(iH,jH,sH); Hs = sum(H,2);
return H,Hs
end
## SUB FUNCTION: EBHM3D
function EBHM3D(den, lx, ly, lz, E0, Emin, nu, penal)
# the initial definitions of the PUC
D0 = E0/(1+nu)/(1-2*nu)*
[ 1-nu nu nu 0 0 0 ;
nu 1-nu nu 0 0 0 ;
nu nu 1-nu 0 0 0 ;
0 0 0 (1-2*nu)/2 0 0 ;
0 0 0 0 (1-2*nu)/2 0 ;
0 0 0 0 0 (1-2*nu)/2];
nely, nelx, nelz = size(den); nele = nelx*nely*nelz;
dx = lx/nelx; dy = ly/nely; dz = lz/nelz;
Ke = elementMatVec3D(dx/2, dy/2, dz/2, D0);
Num_node = (1+nely)*(1+nelx)*(1+nelz);
nodenrs = reshape(1:Num_node,1+nely,1+nelx,1+nelz);
edofVec = reshape(3*nodenrs[1:end-1,1:end-1,1:end-1]+1,nelx*nely*nelz,1);
edofMat = repmat(edofVec,1,24)+repmat( [0 1 2 3*nely+[3 4 5 0 1 2] -3 -2 -1
3*(nelx+1)*(nely+1)+[0 1 2 3*nely+[3 4 5 0 1 2] -3 -2 -1]], nele, 1);
# 3D periodic boundary formulation
# the nodes classification
n1 = [nodenrs[end, [1 end], 1] nodenrs[1, [end 1], 1] nodenrs[end, [1 end], end] nodenrs[1, [end 1], end]];
d1 = reshape( [3*n1-2; 3*n1-1; 3*n1],3*numel(n1),1);
n3 = [reshape(squeeze(nodenrs[end,1,2:end-1] ),1,numel(squeeze(nodenrs[end,1,2:end-1] ))) # AE
reshape(squeeze(nodenrs[1, 1, 2:end-1] ),1,numel(squeeze(nodenrs[1, 1, 2:end-1] ))) # DH
reshape(squeeze(nodenrs[end,2:end-1,1] ),1,numel(squeeze(nodenrs[end,2:end-1,1] ))) # AB
reshape(squeeze(nodenrs[1, 2:end-1, 1] ),1,numel(squeeze(nodenrs[1, 2:end-1, 1] ))) # DC
reshape(squeeze(nodenrs[2:end-1, 1, 1] ),1,numel(squeeze(nodenrs[2:end-1, 1, 1] ))) # AD
reshape(squeeze(nodenrs[2:end-1,1,end] ),1,numel(squeeze(nodenrs[2:end-1,1,end] ))) # EH
reshape(squeeze(nodenrs[2:end-1, 2:end-1, 1] ),1,numel(squeeze(nodenrs[2:end-1, 2:end-1, 1] ))) # ABCD
reshape(squeeze(nodenrs[2:end-1, 1, 2:end-1] ),1,numel(squeeze(nodenrs[2:end-1, 1, 2:end-1] ))) # ADHE
reshape(squeeze(nodenrs[end,2:end-1,2:end-1] ),1,numel(squeeze(nodenrs[end,2:end-1,2:end-1] )))]; # ABFE
d3 = reshape( [3*n3-2; 3*n3-1; 3*n3],3*numel(n3),1);
n4 = [reshape(squeeze(nodenrs[1, end, 2:end-1] ),1,numel(squeeze(nodenrs[1, end, 2:end-1] ))) # CG
reshape(squeeze(nodenrs[end,end,2:end-1] ),1,numel(squeeze(nodenrs[end,end,2:end-1] ))) # BF
reshape(squeeze(nodenrs[1, 2:end-1, end] ),1,numel(squeeze(nodenrs[1, 2:end-1, end] ))) # HG
reshape(squeeze(nodenrs[end,2:end-1,end] ),1,numel(squeeze(nodenrs[end,2:end-1,end] ))) # EF
reshape(squeeze(nodenrs[2:end-1,end,end] ),1,numel(squeeze(nodenrs[2:end-1,end,end] ))) # FG
reshape(squeeze(nodenrs[2:end-1, end, 1] ),1,numel(squeeze(nodenrs[2:end-1, end, 1] ))) # BC
reshape(squeeze(nodenrs[2:end-1,2:end-1,end] ),1,numel(squeeze(nodenrs[2:end-1,2:end-1,end] ))) # EFGH
reshape(squeeze(nodenrs[2:end-1,end,2:end-1] ),1,numel(squeeze(nodenrs[2:end-1,end,2:end-1] ))) # BCGF
reshape(squeeze(nodenrs[1, 2:end-1, 2:end-1] ),1,numel(squeeze(nodenrs[1, 2:end-1, 2:end-1] )))]; # DCGH
d4 = reshape( [3*n4-2; 3*n4-1; 3*n4],3*numel(n4),1);
n2 = setdiff(nodenrs[:],[n1[:];n3[:];n4[:]] ); d2 = reshape( [3*n2-2; 3*n2-1; 3*n2],3*numel(n2),1);
# the imposing of six linearly independent unit test strains
e = Matrix(1.0I, 6, 6);
ufixed = zeros(24,6);
vert_cor = [0 lx lx 0 0 lx lx 0;
0 0 ly ly 0 0 ly ly;
0 0 0 0 lz lz lz lz];
for i = 1:6
epsilon = [ e[i,1] e[i,4]/2 e[i,6]/2;
e[i,4]/2 e[i,2] e[i,5]/2;
e[i,6]/2 e[i,5]/2 e[i,3]];
ufixed[:,i] = reshape(epsilon*vert_cor,24,1);
end
# 3D boundary constraint equations
wfixed = [repmat(ufixed[ 7:9,:],numel(squeeze(nodenrs[end,1,2:end-1] )),1); # C
repmat(ufixed[ 4:6,:]-ufixed[10:12,:],numel(squeeze(nodenrs[1, 1, 2:end-1] )),1); # B-D
repmat(ufixed[22:24,:],numel(squeeze(nodenrs[end,2:end-1,1] )),1); # H
repmat(ufixed[13:15,:]-ufixed(10:12,:),numel(squeeze(nodenrs[1, 2:end-1, 1] )),1); # E-D
repmat(ufixed[16:18,:],numel(squeeze(nodenrs[2:end-1, 1, 1] )),1); # F
repmat(ufixed[ 4:6,:]-ufixed[13:15,:],numel(squeeze(nodenrs[2:end-1,1,end] )),1); # B-E
repmat(ufixed[13:15,:],numel(squeeze(nodenrs[2:end-1, 2:end-1, 1] )),1); # E
repmat(ufixed[ 4:6,:],numel(squeeze(nodenrs[2:end-1, 1, 2:end-1] )),1); # B
repmat(ufixed[10:12,:],numel(squeeze(nodenrs[end,2:end-1,2:end-1] )),1)]; # D
# the reduced elastic equilibrium equation to compute the induced displacement field
iK = reshape(kron(edofMat,ones(24,1))',24*24*nele,1);
jK = reshape(kron(edofMat,ones(1,24))',24*24*nele,1);
sK = reshape(Ke[:]*(Emin+den[:]'.^penal*(1-Emin)),24*24*nele,1);
K = sparse(iK[:], jK[:], sK[:] ); K = (K+K')/2;
Kr = [K[d2,d2], K[d2,d3]+K[d2,d4]; K[d3,d2]+K[d4,d2],K[d3,d3]+K[d4,d3]+K[d3,d4]+K[d4,d4]];
U[d1,:]= ufixed;
U[ [d2;d3],:] = Kr\(-[K[d2,d1];K[d3,d1]+K[d4,d1]]*ufixed-[K[d2,d4];K[d3,d4]+K[d4,d4]]*wfixed);
U[d4,:] = U[d3,:] + wfixed;
# homogenization to evaluate macroscopic effective properties
qe = Array{Any,2}(undef, 6, 6);
DH = zeros(6,6);
dDH = Array{Any,2}(undef, 6, 6);
cellVolume = lx*ly*lz;
for i = 1:6
for j = 1:6
U1 = U[:,i]; U2 = U[:,j];
qe[i,j] = reshape(sum((U1[edofMat]*Ke).*U2[edofMat],dims=2),nely,nelx,nelz);
DH[i,j] = 1/cellVolume*sum(sum(sum((Emin+den.^penal*(1-Emin)).*qe{i,j})));
dDH[i,j] = 1/cellVolume*(penal*(1-Emin)*den.^(penal-1).*qe{i,j});
end
end
# disp('--- Homogenized elasticity tensor ---'); disp(DH)
return DH, dDH
end
## SUB FUNCTION: elementMatVec3D
function elementMatVec3D(a, b, c, DH)
GN_x=[-1/sqrt(3),1/sqrt(3)]; GN_y=GN_x; GN_z=GN_x; GaussWeigh=[1,1];
Ke = zeros(24,24); L = zeros(6,9);
L[1,1] = 1; L[2,5] = 1; L[3,9] = 1;
L[4,2] = 1; L[4,4] = 1; L[5,6] = 1;
L[5,8] = 1; L[6,3] = 1; L[6,7] = 1;
for ii=1:length(GN_x)
for jj=1:length(GN_y)
for kk=1:length(GN_z)
x = GN_x[ii];y = GN_y[jj];z = GN_z[kk];
dNx = 1/8*[-(1-y)*(1-z) (1-y)*(1-z) (1+y)*(1-z) -(1+y)*(1-z) -(1-y)*(1+z) (1-y)*(1+z) (1+y)*(1+z) -(1+y)*(1+z)];
dNy = 1/8*[-(1-x)*(1-z) -(1+x)*(1-z) (1+x)*(1-z) (1-x)*(1-z) -(1-x)*(1+z) -(1+x)*(1+z) (1+x)*(1+z) (1-x)*(1+z)];
dNz = 1/8*[-(1-x)*(1-y) -(1+x)*(1-y) -(1+x)*(1+y) -(1-x)*(1+y) (1-x)*(1-y) (1+x)*(1-y) (1+x)*(1+y) (1-x)*(1+y)];
J = [dNx;dNy;dNz]*[ -a a a -a -a a a -a ; -b -b b b -b -b b b; -c -c -c -c c c c c]';
G = [inv(J) zeros(3) zeros(3);zeros(3) inv(J) zeros(3);zeros(3) zeros(3) inv(J)];
dN=zeros(9,24)
dN[1,1:3:24] = dNx; dN[2,1:3:24] = dNy; dN[3,1:3:24] = dNz;
dN[4,2:3:24] = dNx; dN[5,2:3:24] = dNy; dN[6,2:3:24] = dNz;
dN[7,3:3:24] = dNx; dN[8,3:3:24] = dNy; dN[9,3:3:24] = dNz;
Be = L*G*dN;
Ke = Ke + GaussWeigh[ii]*GaussWeigh[jj]*GaussWeigh[kk]*det(J)*(Be'*DH*Be);
end
end
end
return Ke
end
## SUB FUNCTION: OC
function OC(x, dc, dv, H, Hs, volfrac, nele, move, beta)
l1 = 0; l2 = 1e9;
while (l2-l1)/(l1+l2) > 1e-3
lmid = 0.5*(l2+l1);
xnew = max(0,max(x-move,min(1,min(x+move,x.*sqrt(-dc./dv/lmid)))));
xTilde[:] = (H*xnew[:] )./Hs; xPhys = 1-exp(-beta*xTilde)+xTilde*exp(-beta);
if sum(xPhys[:] ) > volfrac*nele
l1 = lmid;
else
l2 = lmid;
end
end
change = max(abs(xnew[:]-x[:] )); x = xnew;
return x, xPhys, change
end
## SUB FUNCTION: display_3D
function display_3D(rho)
[nely,nelx,nelz] = size(rho);
hx = 1; hy = 1; hz = 1;
face = [1 2 3 4; 2 6 7 3; 4 3 7 8; 1 5 8 4; 1 2 6 5; 5 6 7 8];
# set(gcf,'Name','ISO display','NumberTitle','off');
for k = 1:nelz
z = (k-1)*hz;
for i = 1:nelx
x = (i-1)*hx;
for j = 1:nely
y = nely*hy - (j-1)*hy;
if (rho[j,i,k] > 0)
vert = [x y z; x y-hx z; x+hx y-hx z; x+hx y z; x y z+hx;x y-hx z+hx; x+hx y-hx z+hx;x+hx y z+hx];
vert[:,[2 3]] = vert[:,[3 2]]; vert[:,2,:] = -vert[:,2,:];
# patch('Faces',face,'Vertices',vert,'FaceColor',[0.2+0.8*(1-rho(j,i,k)),0.2+0.8*(1-rho(j,i,k)),0.2+0.8*(1-rho(j,i,k))] );
# hold on;
end
end
end
end
# axis equal; axis tight; axis off; box on; view( [30,30] ); pause(1e-6);
end
#======================================================================================================================#
# Function ConTop3D: #
# A compact and efficient MATLAB code for Concurrent topology optimization of multiscale composite structures #
# in Matlab. #
# #
# Developed by: Jie Gao, Zhen Luo, Liang Xia and Liang Gao* #
# Email: gaoliang@mail.hust.edu.cn (GabrielJie_Tian@163.com) #
# #
# Main references: #
# #
# (1) Jie Gao, Zhen Luo, Liang Xia, Liang Gao. Concurrent topology optimization of multiscale composite structures #
# in Matlab. Accepted in Structural and multidisciplinary optimization. #
# #
# (2) Xia L, Breitkopf P. Design of materials using topology optimization and energy-based homogenization approach in #
# Matlab. # Structural and multidisciplinary optimization, 2015, 52(6): 1229-1241. #
# #
# ********************************************* Disclaimer ******************************************************* #
# The authors reserve all rights for the programs. The programs may be distributed and used for academic and #
# educational purposes. The authors do not guarantee that the code is free from errors,and they shall not be liable #
# in any event caused by the use of the program. #
#======================================================================================================================#