Skip to content
Snippets Groups Projects
concurrent2D.jl 12.1 KiB
Newer Older
  • Learn to ignore specific revisions
  • function ConTop2D(Macro_struct, Micro_struct, penal, rmin)
        ## USER-DEFINED LOOP PARAMETERS
        maxloop = 200; E0 = 1; Emin = 1e-9; nu = 0.3;
    
        Macro_length = Macro_struct[1]; Macro_width = Macro_struct[2];
        Micro_length = Micro_struct[1]; Micro_width = Micro_struct[2];
        Macro_nelx   = Macro_struct[3]; Macro_nely  = Macro_struct[4];
        Micro_nelx   = Micro_struct[3]; Micro_nely  = Micro_struct[4];
        Macro_Vol    = Macro_struct[5]; Micro_Vol   = Micro_struct[5];
    
        Macro_Elex = Macro_length/Macro_nelx; Macro_Eley = Macro_width/Macro_nely;
        Macro_nele = Macro_nelx*Macro_nely;   Micro_nele = Micro_nelx*Micro_nely;
        Macro_ndof = 2*(Macro_nelx+1)*(Macro_nely+1);
    
        # PREPARE FINITE ELEMENT ANALYSIS
        [load_x, load_y] = meshgrid(Macro_nelx, Macro_nely/2);
        loadnid  = load_x*(Macro_nely+1)+(Macro_nely+1-load_y);
        F = sparse(2*loadnid[:], 1, -1, 2*(Macro_nelx+1)*(Macro_nely+1),1);
        U = zeros(Macro_ndof,1);
    
        [fixed_x, fixed_y] = meshgrid(0, 0:Macro_nely);
        fixednid  = fixed_x*(Macro_nely+1)+(Macro_nely+1-fixed_y);
        fixeddofs = [2*fixednid[:]; 2*fixednid[:]-1];
        freedofs  = setdiff(1:Macro_ndof,fixeddofs);
        nodenrs = reshape(1:(Macro_nely+1)*(Macro_nelx+1),1+Macro_nely,1+Macro_nelx);
        edofVec = reshape(2*nodenrs( [1:end-1,1:end-1] )+1,Macro_nele,1);
        edofMat = repmat(edofVec,1,8)+repmat( [0 1 2*Macro_nely+[2 3 0 1] -2 -1],Macro_nele,1);
    
        iK = reshape(kron(edofMat,ones(8,1))',64*Macro_nele,1);
        jK = reshape(kron(edofMat,ones(1,8))',64*Macro_nele,1);
        # PREPARE FILTER
        Macro_H,Macro_Hs = filtering2d(Macro_nelx, Macro_nely, Macro_nele, rmin);
        Micro_H,Micro_Hs = filtering2d(Micro_nelx, Micro_nely, Micro_nele, rmin);
    
    
        # INITIALIZE ITERATION
        Macro_x = repmat(Macro_Vol,Macro_nely,Macro_nelx);
        Micro_x = ones(Micro_nely,Micro_nelx);
        for i = 1:Micro_nelx
            for j = 1:Micro_nely
                if sqrt((i-Micro_nelx/2-0.5)^2+(j-Micro_nely/2-0.5)^2) < min(Micro_nelx,Micro_nely)/3
                    Micro_x(j,i) = 0;
                end
            end
        end
    
        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 = EBHM2D(Micro_xPhys, Micro_length, Micro_width, E0, Emin, nu, penal);
    
            Ke = elementMatVec2D(Macro_Elex/2, Macro_Eley/2, DH);
            sK = reshape(Ke[:]*(Emin+Macro_xPhys[:]'.^penal*(1-Emin)),64*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);
            c = 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);
            Micro_dc = zeros(Micro_nely, Micro_nelx);
            for i = 1:Micro_nele
                dDHe = [dDH[1,1][i] dDH[1,2][i] dDH[1,3][i];
                        dDH[2,1][i] dDH[2,2][i] dDH[2,3][i];
                        dDH[3,1][i] dDH[3,2][i] dDH[3,3][i]];
                dKE = elementMatVec2D(Macro_Elex, Macro_Eley, dDHe);
                dce = reshape(sum((U[edofMat]*dKE).*U[edofMat],2),Macro_nely,Macro_nelx);
                Micro_dc[i] = -sum(sum((Emin+Macro_xPhys.^penal*(1-Emin)).*dce));
            end
            Micro_dv = ones(Micro_nely, Micro_nelx);
            
            # 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.2, beta);
            Micro_x, Micro_xPhys, Micro_change = OC(Micro_x, Micro_dc, Micro_dv, Micro_H, Micro_Hs, Micro_Vol, Micro_nele, 0.2, beta);
            Macro_xPhys = reshape(Macro_xPhys, Macro_nely, Macro_nelx); 
            Micro_xPhys = reshape(Micro_xPhys, Micro_nely, Micro_nelx);
            # 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);
            # colormap(gray); imagesc(1-Macro_xPhys); caxis( [0 1] ); axis equal; axis off; drawnow;
            # colormap(gray); imagesc(1-Micro_xPhys); caxis( [0 1] ); axis equal; axis off; drawnow;
    
            ## 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:filtering2D
    function filtering2d(nelx, nely, nele, rmin)
        iH = ones(nele*(2*(ceil(rmin)-1)+1)^2,1);
        jH = ones(size(iH));
        sH = zeros(size(iH));
        k = 0;
        for i1 = 1:nelx
            for j1 = 1:nely
                e1 = (i1-1)*nely+j1;
                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 = (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));
                    end
                end
            end
        end
        H = sparse(iH,jH,sH); Hs = sum(H,2);
        return H,Hs
    end
    
    ## SUB FUNCTION: EBHM2D
    function EBHM2D(den, lx, ly, E0, Emin, nu, penal)
        # the initial definitions of the PUC
        D0=E0/(1-nu^2)*[1 nu 0; nu 1 0; 0 0 (1-nu)/2];  # the elastic tensor
        nely, nelx = size(den);
        nele = nelx*nely;
        dx = lx/nelx; dy = ly/nely;
        Ke = elementMatVec2D(dx/2, dy/2, D0);
        Num_node = (1+nely)*(1+nelx);
        nodenrs = reshape(1:Num_node,1+nely,1+nelx);
        edofVec = reshape(2*nodenrs[1:end-1,1:end-1]+1,nele,1);
        edofMat = repmat(edofVec,1,8)+repmat( [0 1 2*nely+[2 3 0 1] -2 -1],nele,1);
        # 3D periodic boundary formulation
        alldofs = (1:2*(nely+1)*(nelx+1));
        n1 = [nodenrs[end,[1,end]],nodenrs[1,[end,1]]];
        d1 = reshape( [(2*n1-1);2*n1],1,8);
        n3 = [nodenrs[2:end-1,1]',nodenrs[end,2:end-1]];
        d3 = reshape( [(2*n3-1);2*n3],1,2*(nelx+nely-2));
        n4 = [nodenrs[2:end-1,end]',nodenrs[1,2:end-1]];
        d4 = reshape( [(2*n4-1);2*n4],1,2*(nelx+nely-2));
        d2 = setdiff(alldofs,[d1,d3,d4] );
        e0 = Matrix(1.0I, 3, 3);
        ufixed = zeros(8,3);
        for j = 1:3
            ufixed[3:4,j] = [e0[1,j],e0[3,j]/2;e0[3,j]/2,e0[2,j]]*[lx;0];
            ufixed[7:8,j] = [e0[1,j],e0[3,j]/2;e0[3,j]/2,e0[2,j]]*[0;ly];
            ufixed[5:6,j] = ufixed[3:4,j]+ufixed[7:8,j];
        end
        wfixed = [repmat(ufixed[3:4,:],nely-1,1);repmat(ufixed[7:8,:],nelx-1,1)];
        # the reduced elastic equilibrium equation to compute the induced displacement field
        iK = reshape(kron(edofMat,ones(8,1))',64*nelx*nely,1);
        jK = reshape(kron(edofMat,ones(1,8))',64*nelx*nely,1);
    
        sK = reshape(Ke[:]*(Emin+den[:]'.^penal*(1-Emin)),64*nelx*nely,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
        DH = zeros(3); 
        qe = Array{Any,2}(undef, 3, 3); 
        dDH = Array{Any,2}(undef, 3, 3);
    
        cellVolume = lx*ly;
        for i = 1:3
            for j = 1:3
                U1 = U[:,i]; U2 = U[:,j];
                qe[i,j] = reshape(sum((U1[edofMat]*Ke).*U2[edofMat],dims=2),nely,nelx)/cellVolume;
                DH[i,j] = sum(sum((Emin+den.^penal*(1-Emin)).*qe[i,j] ));
                dDH[i,j] = penal*(1-Emin)*den.^(penal-1).*qe[i,j];
            end
        end
        # disp("--- Homogenized elasticity tensor ---"); disp(DH)
        return DH, dDH
    end
    
    ## SUB FUNCTION: elementMatVec2D
    function elementMatVec2D(a, b, DH)
        GaussNodes = [-1/sqrt(3); 1/sqrt(3)]; 
        GaussWeigh = [1 1];
        L = [1 0 0 0; 0 0 0 1; 0 1 1 0];
        Ke = zeros(8,8);
        for i = 1:2
            for j = 1:2
                GN_x = GaussNodes[i]; 
                GN_y = GaussNodes[j];
    
                dN_x = 1/4*[-(1-GN_x)  (1-GN_x) (1+GN_x) -(1+GN_x)];
                dN_y = 1/4*[-(1-GN_y) -(1+GN_y) (1+GN_y)  (1-GN_y)];
    
                J = [dN_x; dN_y]*[ -a  a  a  -a;  -b  -b  b  b]';
                G = [inv(J) zeros(size(J)); zeros(size(J)) inv(J)];
                dN[1,1:2:8] = dN_x; 
                dN[2,1:2:8] = dN_y;
                dN[3,2:2:8] = dN_x; 
                dN[4,2:2:8] = dN_y;
                Be = L*G*dN;
                Ke = Ke + GaussWeigh[i]*GaussWeigh[j]*det(J)*Be'*DH*Be;
            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-4
            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
    #======================================================================================================================#
    # Function ConTop2D:                                                                                                   #
    # 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.                                                                       #
    #======================================================================================================================#