%%% A 135 line code for topology optimization with same size elements, 3D version. Vittorio Latorre Jan. 2019 %%% function [xPhys,c,loop]=tosse3d(nelx,nely,nelz,volfrac,mu) %% USER-DEFINED LOOP PARAMETERS & MATERIAL PROPERTIES maxloop = 50; % Maximum number of iterations E0 = 1; % Young's modulus of solid material Emin = 1e-9; % Young's modulus of void-like material nu = 0.3; % Poisson's ratio %% USER-DEFINED LOAD DOFs [il,jl,kl] = meshgrid(nelx, 0, 0:nelz); % Coordinates loadnid = kl*(nelx+1)*(nely+1)+il*(nely+1)+(nely+1-jl); % Node IDs loaddof = 3*loadnid(:) - 1; % DOFs %% USER-DEFINED SUPPORT FIXED DOFs [iif,jf,kf] = meshgrid(0,0:nely,0:nelz); % Coordinates fixednid = kf*(nelx+1)*(nely+1)+iif*(nely+1)+(nely+1-jf); % Node IDs fixeddof = [3*fixednid(:); 3*fixednid(:)-1; 3*fixednid(:)-2]; % DOFs %% PREPARE FINITE ELEMENT ANALYSIS nele = nelx*nely*nelz; ndof = 3*(nelx+1)*(nely+1)*(nelz+1); F = sparse(loaddof,1,-1,ndof,1); U = zeros(ndof,1); freedofs = setdiff(1:ndof,fixeddof); KE = lk_H8(nu); nodegrd = reshape(1:(nely+1)*(nelx+1),nely+1,nelx+1); nodeids = reshape(nodegrd(1:end-1,1:end-1),nely*nelx,1); nodeidz = 0:(nely+1)*(nelx+1):(nelz-1)*(nely+1)*(nelx+1); nodeids = repmat(nodeids,size(nodeidz))+repmat(nodeidz,size(nodeids)); edofVec = 3*nodeids(:)+1; edofMat = repmat(edofVec,1,24)+ ... repmat([0 1 2 3*nely + [3 4 5 0 1 2] -3 -2 -1 ... 3*(nely+1)*(nelx+1)+[0 1 2 3*nely + [3 4 5 0 1 2] -3 -2 -1]],nele,1); iK = reshape(kron(edofMat,ones(24,1))',24*24*nele,1); jK = reshape(kron(edofMat,ones(1,24))',24*24*nele,1); %% INITIALIZE ITERATION vgam=1; loop = 0; change = 1; xPhys = ones(nely,nelx,nelz)*vgam; %% START ITERATION while change > 0 && loop < maxloop loop = loop+1; vgam = max(volfrac,vgam*mu); %% FE-ANALYSIS sK = reshape(KE(:)*(Emin+xPhys(:)'.*(E0-Emin)),24*24*nele,1); K = sparse(iK,jK,sK); K = (K+K')/2; U(freedofs,:) = K(freedofs,freedofs)\F(freedofs,:); %% OBJECTIVE FUNCTION AND SENSITIVITY ANALYSIS ce = (xPhys(:)+Emin)*E0.*(sum((U(edofMat)*KE).*U(edofMat),2)); c = sum((Emin+ce*(1-Emin/E0))); %% SOLVE THE KNAPSACK PROBLEM [~,I]=sort(ce,1,'descend'); xnew=zeros(nelx*nely,1); xnew(I(1:floor(vgam*nelx*nely*nelz)))=1; change = max(abs(xnew(:)-xPhys(:))); xPhys=reshape(xnew,[nely,nelx,nelz]); %% PRINT RESULTS fprintf(' It.:%5i Obj.:%11.4f Vol.:%7.3f ch.:%7.3f\n',loop,c,mean(xPhys(:)),change); end %% PLOT DENSITIES clf; display_3D(xPhys); TimeMinute=toc/(60); title(['TOSSE3D:',' Vc=',num2str((volfrac)),', nex= ',num2str(nelx), ', ney=',num2str(abs(nely)),... ', nez=',num2str(abs(nelz)),', C=',num2str(c),', It=',num2str(loop),', TM=',num2str(TimeMinute)]); xlabel(['nelx= ',num2str(nelx),' nely= ',num2str(abs(nely)),' nelz= ',num2str(abs(nelz))]); end % === GENERATE ELEMENT STIFFNESS MATRIX === function [KE] = lk_H8(nu) A = [32 6 -8 6 -6 4 3 -6 -10 3 -3 -3 -4 -8; -48 0 0 -24 24 0 0 0 12 -12 0 12 12 12]; k = 1/144*A'*[1; nu]; K1 = [k(1) k(2) k(2) k(3) k(5) k(5); k(2) k(1) k(2) k(4) k(6) k(7); k(2) k(2) k(1) k(4) k(7) k(6); k(3) k(4) k(4) k(1) k(8) k(8); k(5) k(6) k(7) k(8) k(1) k(2); k(5) k(7) k(6) k(8) k(2) k(1)]; K2 = [k(9) k(8) k(12) k(6) k(4) k(7); k(8) k(9) k(12) k(5) k(3) k(5); k(10) k(10) k(13) k(7) k(4) k(6); k(6) k(5) k(11) k(9) k(2) k(10); k(4) k(3) k(5) k(2) k(9) k(12) k(11) k(4) k(6) k(12) k(10) k(13)]; K3 = [k(6) k(7) k(4) k(9) k(12) k(8); k(7) k(6) k(4) k(10) k(13) k(10); k(5) k(5) k(3) k(8) k(12) k(9); k(9) k(10) k(2) k(6) k(11) k(5); k(12) k(13) k(10) k(11) k(6) k(4); k(2) k(12) k(9) k(4) k(5) k(3)]; K4 = [k(14) k(11) k(11) k(13) k(10) k(10); k(11) k(14) k(11) k(12) k(9) k(8); k(11) k(11) k(14) k(12) k(8) k(9); k(13) k(12) k(12) k(14) k(7) k(7); k(10) k(9) k(8) k(7) k(14) k(11); k(10) k(8) k(9) k(7) k(11) k(14)]; K5 = [k(1) k(2) k(8) k(3) k(5) k(4); k(2) k(1) k(8) k(4) k(6) k(11); k(8) k(8) k(1) k(5) k(11) k(6); k(3) k(4) k(5) k(1) k(8) k(2); k(5) k(6) k(11) k(8) k(1) k(8); k(4) k(11) k(6) k(2) k(8) k(1)]; K6 = [k(14) k(11) k(7) k(13) k(10) k(12); k(11) k(14) k(7) k(12) k(9) k(2); k(7) k(7) k(14) k(10) k(2) k(9); k(13) k(12) k(10) k(14) k(7) k(11); k(10) k(9) k(2) k(7) k(14) k(7); k(12) k(2) k(9) k(11) k(7) k(14)]; KE = 1/((nu+1)*(1-2*nu))*... [ K1 K2 K3 K4; K2' K5 K6 K3'; K3' K6 K5' K2'; K4 K3 K2 K1']; end % === DISPLAY 3D TOPOLOGY (ISO-VIEW) === function display_3D(rho) [nely,nelx,nelz] = size(rho); hx = 1; hy = 1; hz = 1; % User-defined unit element size 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.5) % User-defined display density threshold 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 %%%This code is partially based on the code reported in: %%% %%%"An efficient 3D topology optimization code written in Matlab" %%% %%%By Kai Liu and Andres Tovar. %%%