Skip to content
Snippets Groups Projects
topologyOptimization.jl 106 KiB
Newer Older
  • Learn to ignore specific revisions
  •     # loaddof=[getIndex3d1(1,nely+1,1,1,nelx+1,nely+1,nelz+1,3),
        #     getIndex3d1(nelx+1,nely+1,1,1,nelx+1,nely+1,nelz+1,3)]
        # din = loaddof[1]; 
        # dout = loaddof[2];
    
        # F = sparse(loaddof,[1;2],[1;-1],ndof,2);
    
        loaddof=[getIndex3d(nelx/2,nely+1,1,1,nelx+1,nely+1,nelz+1,3),
            getIndex3d(nelx+1,nely+1,1,2,nelx+1,nely+1,nelz+1,3)]
        din = loaddof[1]; 
        dout = loaddof[2];
    
        F = sparse(loaddof,[1;2],[-1;-1],ndof,2);
    
    
        # Side face
        m = Matlab.meshgrid(0:nelx,0:nely)
        iif=m[1]
        jf=m[2]
        fixednid = iif .*(nely+1) .+(nely+1 .-jf);
        fixeddof_s = 3*fixednid[:];
    
        fixeddof=union(fixeddof_s,getIndex3d(1,1,(nelz+1),1:3,nelx+1,nely+1,nelz+1,3))
        fixeddof=union(fixeddof,getIndex3d(1,2,(nelz+1),1:3,nelx+1,nely+1,nelz+1,3))
        # fixeddof=union(getIndex3d(1,1,1:(nelz+1),1,nelx+1,nely+1,nelz+1,3),getIndex3d(1,1,1:(nelz+1),2,nelx+1,nely+1,nelz+1,3))
        # fixeddof=union(fixeddof,getIndex3d(1,1,1:(nelz+1),3,nelx+1,nely+1,nelz+1,3))
        # fixeddof=union(fixeddof,getIndex3d(1,2,1:(nelz+1),1,nelx+1,nely+1,nelz+1,3))
        # fixeddof=union(fixeddof,getIndex3d(1,2,1:(nelz+1),2,nelx+1,nely+1,nelz+1,3))
        # fixeddof=union(fixeddof,getIndex3d(1,2,1:(nelz+1),3,nelx+1,nely+1,nelz+1,3))
        fixeddof = sort(fixeddof);
    
    
        # Displacement vector
        U = zeros(ndof,2);
        freedofs = setdiff(1:ndof,fixeddof);
    
        return U,F,freedofs,din,dout
    end
    
    function wing2(nelx,nely,nelz)
        ndof = 3*(nelx+1)*(nely+1)*(nelz+1)
        # USER-DEFINED LOAD DOFs
        # loaddof=[getIndex3d1(1,nely+1,1,1,nelx+1,nely+1,nelz+1,3),
        #     getIndex3d1(nelx+1,nely+1,1,1,nelx+1,nely+1,nelz+1,3)]
        # din = loaddof[1]; 
        # dout = loaddof[2];
    
        # F = sparse(loaddof,[1;2],[1;-1],ndof,2);
    
        loaddof=[getIndex3d(nelx+1,nely+1,1,2,nelx+1,nely+1,nelz+1,3),getIndex3d(1,nely+1,1,1,nelx+1,nely+1,nelz+1,3)]
        din = loaddof[1]; 
        dout = loaddof[2];
    
        F = sparse(loaddof,[1;2],[2;1],ndof,2);
    
        # F = fill(0.0,ndof,2);
    
        # F[loaddof[1],1]=1
        # F[loaddof[2],2]=-1
        # F[getIndex3d(1,1,1,2,nelx+1,nely+1,nelz+1,3):3:getIndex3d(nelx+1,nely+1,nelz+1,2,nelx+1,nely+1,nelz+1,3),1] .+= -0.01
        # F[getIndex3d(1,1,1,2,nelx+1,nely+1,nelz+1,3),1] = 1
        # F[loaddof[1],1].=F[loaddof[1],1].+1.0
        # F = sparse(loaddof,[1;2],[1;1],ndof,2);
        # F[:]
    
    
        # USER-DEFINED SUPPORT FIXED DOFs
        # m= Matlab.meshgrid(0:0,0:nely,0:nelz)# Coordinates
        # iif=m[1]
        # jf=m[2]
        # kf=m[3]
        # fixednid = kf.*(nelx+1).*(nely+1) .+iif .*(nely .+1) .+(nely .+1 .-jf) # Node IDs
        # fixeddof = [3 .*fixednid[:]; 3 .*fixednid[:].-1; 3 .*fixednid[:].-2] # DOFs
    
        # Side face
        m = Matlab.meshgrid(0:nelx,0:nely)
        iif=m[1]
        jf=m[2]
        fixednid = iif .*(nely+1) .+(nely+1 .-jf);
        fixeddof_s = 3*fixednid[:];
    
        fixeddof=union(fixeddof_s,getIndex3d(1,1,(nelz+1),1:3,nelx+1,nely+1,nelz+1,3))
        fixeddof=union(fixeddof,getIndex3d(1,2,(nelz+1),1:3,nelx+1,nely+1,nelz+1,3))
        # fixeddof=union(getIndex3d(1,1,1:(nelz+1),1,nelx+1,nely+1,nelz+1,3),getIndex3d(1,1,1:(nelz+1),2,nelx+1,nely+1,nelz+1,3))
        # fixeddof=union(fixeddof,getIndex3d(1,1,1:(nelz+1),3,nelx+1,nely+1,nelz+1,3))
        # fixeddof=union(fixeddof,getIndex3d(1,2,1:(nelz+1),1,nelx+1,nely+1,nelz+1,3))
        # fixeddof=union(fixeddof,getIndex3d(1,2,1:(nelz+1),2,nelx+1,nely+1,nelz+1,3))
        # fixeddof=union(fixeddof,getIndex3d(1,2,1:(nelz+1),3,nelx+1,nely+1,nelz+1,3))
        fixeddof = sort(fixeddof);
    
    
        # Displacement vector
        U = zeros(ndof,2);
        freedofs = setdiff(1:ndof,fixeddof);
    
        return U,F,freedofs,din,dout
    end
    
    #############################################2d Periodic############################################################
    # Based on https://link.springer.com/article/10.1007/s00158-015-1294-0
    ## PERIODIC MATERIAL MICROSTRUCTURE DESIGN
    function topX(nelx,nely,volfrac,penal,rmin,ft,optType="bulk")
        ## MATERIAL PROPERTIES
        E0 = 1;
        Emin = 1e-9;
        nu = 0.3;
        ## PREPARE FINITE ELEMENT ANALYSIS
        A11 = [12  3 -6 -3;  3 12  3  0; -6  3 12 -3; -3  0 -3 12]'
        A12 = [-6 -3  0  3; -3 -6 -3 -6;  0 -3 -6  3;  3 -6  3 -6]'
        B11 = [-4  3 -2  9;  3 -4 -9  4; -2 -9 -4 -3;  9  4 -3 -4]'
        B12 = [ 2 -3  4 -9; -3  2  9 -2;  4  9  2  3; -9 -2  3  2]'
        KE = 1/(1-nu^2)/24*([A11 A12;A12' A11]+nu*[B11 B12;B12' B11])
    
        
        nodenrs = reshape(1:(1+nelx)*(1+nely),1+nely,1+nelx)
        edofVec = reshape(2*nodenrs[1:end-1,1:end-1].+1,nelx*nely,1)
        edofMat = repeat(edofVec,1,8).+repeat([0 1 2*nely.+[2 3 0 1] -2 -1],nelx*nely,1)
    
        iK = convert(Array{Int},reshape(kron(edofMat,ones(8,1))',64*nelx*nely,1))
        jK = convert(Array{Int},reshape(kron(edofMat,ones(1,8))',64*nelx*nely,1))
        
        ## PREPARE FILTER
        iH = ones(convert(Int,nelx*nely*(2*(ceil(rmin)-1)+1)^2),1)
        jH = ones(Int,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(vec(iH),vec(jH),vec(sH))
        Hs = sum(H,dims=2)
        
        ## PERIODIC BOUNDARY CONDITIONS
        e0 = Matrix(1.0I, 3, 3);
        ufixed = zeros(8,3);
        
        U = zeros(2*(nely+1)*(nelx+1),3);
        alldofs = [1:2*(nely+1)*(nelx+1)];
        
        n1 = vcat(nodenrs[end,[1,end]],nodenrs[1,[end,1]]);
        d1 = vec(reshape([(2 .* n1 .-1) 2 .*n1]',1,8));
        n3 = [vec(nodenrs[2:(end-1),1]');vec(nodenrs[end,2:(end-1)])];
        d3 = vec(reshape([(2 .*n3 .-1) 2 .*n3]',1,2*(nelx+nely-2)));
        n4 = [vec(nodenrs[2:end-1,end]');vec(nodenrs[1,2:end-1])];
        d4 = vec(reshape([(2 .*n4 .-1) 2 .*n4]',1,2*(nelx+nely-2)));
        d2 = setdiff(vcat(alldofs...),union(union(d1,d3),d4));
        
            
        
        for j = 1:3
            ufixed[3:4,j] = [e0[1,j] e0[3,j]/2 ; e0[3,j]/2 e0[2,j]]*[nelx;0];
            ufixed[7:8,j] = [e0[1,j] e0[3,j]/2 ; e0[3,j]/2 e0[2,j]]*[0;nely];
            ufixed[5:6,j] = ufixed[3:4,j] .+ ufixed[7:8,j];
        end
        wfixed = [repeat(ufixed[3:4,:],nely-1,1); repeat(ufixed[7:8,:],nelx-1,1)];
        
    
        
        ## INITIALIZE ITERATION
        qe = Array{Any,2}(undef, 3, 3);
        Q = zeros(3,3);
        dQ = Array{Any,2}(undef, 3, 3);
        x = volfrac.*ones(nely,nelx)
        
        for i = 1:nelx
            for j = 1:nely
                vall=3
                if optType=="poisson"
                    vall=6
                end
                if sqrt((i-nelx/2-0.5)^2+(j-nely/2-0.5)^2) < min(nelx,nely)/vall
                    x[j,i] = volfrac/2.0;
                end
            end
        end
        xPhys = copy(x);
        change = 1;
        loop = 0;
        xnew=zeros(size(x))
        ## START ITERATION
        while (change > 0.01)
            loop = loop +1;
            ## FE-ANALYSIS
            sK = reshape(KE[:]*(Emin .+ xPhys[:]'.^penal*(80 .- Emin)),64*nelx*nely,1);
            
            K = sparse(vec(iK),vec(jK),vec(sK)); 
            K = (K.+K')./2.0;
            Kr = vcat(hcat(K[d2,d2] , K[d2,d3]+K[d2,d4]),hcat((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;
            
            
            ## OBJECTIVE FUNCTION AND SENSITIVITY ANALYSIS
            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)./(nelx*nely);
                    Q[i,j] = sum(sum((Emin .+ xPhys.^penal*(E0 .-Emin)).*qe[i,j]));
                    dQ[i,j] = penal*(E0-Emin)*xPhys.^(penal-1).*qe[i,j];
                end
            end
            if optType=="bulk"
                #bulk
                c = -(Q[1,1]+Q[2,2]+Q[1,2]+Q[2,1]);
                dc = -(dQ[1,1]+dQ[2,2]+dQ[1,2]+dQ[2,1]);
            elseif optType=="shear"
                #shear
                c=-Q[3,3];
                dc=-dQ[3,3];
            elseif optType=="poisson"
                c = Q[1,2]-(0.8^loop)*(Q[1,1]+Q[2,2]);
                dc = dQ[1,2]-(0.8^loop)*(dQ[1,1]+dQ[2,2]);
            end
            
            dv = ones(nely,nelx);
            ## FILTERING/MODIFICATION OF SENSITIVITIES
            if ft == 1
                dc[:] = H*(x[:].*dc[:])./Hs./max.(1e-3,x[:]);
            elseif ft == 2
                dc[:] = H*(dc[:]./Hs);
                dv[:] = H*(dv[:]./Hs);
            end
            ## OPTIMALITY CRITERIA UPDATE OF DESIGN VARIABLES AND PHYSICAL DENSITIES
                
            if optType=="poisson"
                l1=0; l2=1e9; move = 0.1;
            else
                l1 =0; l2 = 1e9; move = 0.2;
            end
            while (l2-l1 > 1e-9)
                lmid = 0.5*(l2+l1);
                if optType=="poisson"
                    xnew = max.(0,max.(x.-move,min.(1.0,min.(x.+move,x.*(-dc./dv./lmid)))));
    
                    xnew =max.(0.0,max.(x.-move,min.(1.0,min.(x.+move,x.*sqrt.(0.0.-dc./dv./lmid)))));
                end
                if ft == 1
                    xPhys = copy(xnew);
                elseif ft == 2
                    xPhys[:] = (H*xnew[:])./Hs;
                end
                if mean(xPhys[:]) > volfrac
                    l1 = lmid;
                else
                    l2 = lmid;
    
            change = maximum(abs.(xnew[:].-x[:]))
            x = xnew;
            ## PRINT RESULTS
            display(" It:$loop Obj:$c Vol:$(mean(xPhys[:])) ch:$change ")
    
            ## PLOT DENSITIES
            heatmap(xPhys, aspect_ratio=:equal, legend=false, axis=nothing, foreground_color_subplot=colorant"white",fc=:grays,clims=(0.0, 1.0))
            frame(anim)
    
        return xnew
    
    ######################3d Periodic#########################################
    function topX3D(nelx,nely,nelz,volfrac,penal,rmin,ft,optType="bulk")
    
        ## MATERIAL PROPERTIES
        E0 = 1;
        Emin = 1e-9;
        nu = 0.3;
        ## PREPARE FINITE ELEMENT ANALYSIS
    
        KE=lk_H8(nu)
    
        Num_node = (1+nely)*(1+nelx)*(1+nelz);
        nele = nelx*nely*nelz;
    
        nodenrs = reshape(1:(1+nelx)*(1+nely)*(1+nelz),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 = repeat(edofVec,1,24).+repeat([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]],nelx*nely*nelz,1)
    
        iK = reshape(kron(edofMat,ones(24,1))',24*24*nele,1);
        jK = reshape(kron(edofMat,ones(1,24))',24*24*nele,1);
    
    
        ## PREPARE FILTER
        iH = ones(convert(Int,nelx*nely*(2*(ceil(rmin)-1)+1)^2),1)
        jH = ones(Int,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(vec(iH),vec(jH),vec(sH))
        Hs = sum(H,dims=2)
        
        ## PERIODIC BOUNDARY CONDITIONS
    
        e0 = Matrix(1.0I, 6, 6);
        ufixed = zeros(24,6);
    
        
        U = zeros(2*(nely+1)*(nelx+1),3);
        alldofs = [1:2*(nely+1)*(nelx+1)];
        
        n1 = vcat(nodenrs[end,[1,end]],nodenrs[1,[end,1]]);
        d1 = vec(reshape([(2 .* n1 .-1) 2 .*n1]',1,8));
        n3 = [vec(nodenrs[2:(end-1),1]');vec(nodenrs[end,2:(end-1)])];
        d3 = vec(reshape([(2 .*n3 .-1) 2 .*n3]',1,2*(nelx+nely-2)));
        n4 = [vec(nodenrs[2:end-1,end]');vec(nodenrs[1,2:end-1])];
        d4 = vec(reshape([(2 .*n4 .-1) 2 .*n4]',1,2*(nelx+nely-2)));
        d2 = setdiff(vcat(alldofs...),union(union(d1,d3),d4));
    
    
        # 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] );
    
        n1 = vcat(nodenrs[end, [1 end], 1], nodenrs[1, [end 1], 1], nodenrs[end, [1 end], end], nodenrs[1, [end 1], end]);
        d1 = vec(reshape( [3 .*n1-2 3 .*n1-1 3 .*n1]',3*numel(n1),1));
        n3 = vcat(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 = vec(reshape( [3 .*n3-2 3 .*n3-1 3 .*n3]',3*numel(n3),1));
        n4 = vcat(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 = vec(reshape( [3*n4-2 3*n4-1 3*n4]',3*numel(n4),1));
        n2 = setdiff(nodenrs[:],union(n1[:],union(n3[:],n4[:])) ); 
        d2 = vec(reshape( [3*n2-2 3*n2-1 3*n2]',3*numel(n2),1));
        
        # for j = 1:3
        #     ufixed[3:4,j] = [e0[1,j] e0[3,j]/2 ; e0[3,j]/2 e0[2,j]]*[nelx;0];
        #     ufixed[7:8,j] = [e0[1,j] e0[3,j]/2 ; e0[3,j]/2 e0[2,j]]*[0;nely];
        #     ufixed[5:6,j] = ufixed[3:4,j] .+ ufixed[7:8,j];
        # end
        # wfixed = [repeat(ufixed[3:4,:],nely-1,1); repeat(ufixed[7:8,:],nelx-1,1)];
        
    
        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);
    
        # 3D boundary constraint equations
        wfixed = [repeat(ufixed[  7:9,:],numel(squeeze(nodenrs[end,1,2:end-1] )),1);                    # C
                  repeat(ufixed[  4:6,:]-ufixed[10:12,:],numel(squeeze(nodenrs[1, 1, 2:end-1] )),1);    # B-D
                  repeat(ufixed[22:24,:],numel(squeeze(nodenrs[end,2:end-1,1] )),1);                    # H
                  repeat(ufixed[13:15,:]-ufixed(10:12,:),numel(squeeze(nodenrs[1, 2:end-1, 1] )),1);    # E-D
                  repeat(ufixed[16:18,:],numel(squeeze(nodenrs[2:end-1, 1, 1] )),1);                    # F
                  repeat(ufixed[  4:6,:]-ufixed[13:15,:],numel(squeeze(nodenrs[2:end-1,1,end] )),1);    # B-E
                  repeat(ufixed[13:15,:],numel(squeeze(nodenrs[2:end-1, 2:end-1, 1] )),1);              # E
                  repeat(ufixed[  4:6,:],numel(squeeze(nodenrs[2:end-1, 1, 2:end-1] )),1);              # B
                  repeat(ufixed[10:12,:],numel(squeeze(nodenrs[end,2:end-1,2:end-1] )),1)];             # D
    
        qe = Array{Any,2}(undef, 6, 6);
        Q = zeros(6,6);
        dQ = Array{Any,2}(undef, 6, 6);
    
        x = volfrac.*ones(nely,nelx)
        
        for i = 1:nelx
            for j = 1:nely
                vall=3
                if optType=="poisson"
                    vall=6
                end
                if sqrt((i-nelx/2-0.5)^2+(j-nely/2-0.5)^2) < min(nelx,nely)/vall
                    x[j,i] = volfrac/2.0;
                end
            end
        end
        xPhys = copy(x);
        change = 1;
        loop = 0;
        xnew=zeros(size(x))
        ## START ITERATION
        while (change > 0.01)
            loop = loop +1;
            ## FE-ANALYSIS
    
            sK = reshape(KE[:]*(Emin .+ xPhys[:]'.^penal*(80 .- Emin)),24*24*nelx*nely,1);
            # sK = reshape(Ke[:]*(Emin+den[:]'.^penal*(1-Emin)),24*24*nele,1);
    
    
            K = sparse(vec(iK),vec(jK),vec(sK)); 
            K = (K.+K')./2.0;
            Kr = vcat(hcat(K[d2,d2] , K[d2,d3]+K[d2,d4]),hcat((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;
            
            
            ## OBJECTIVE FUNCTION AND SENSITIVITY ANALYSIS
    
            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)./(nelx*nely);
                    Q[i,j] = sum(sum((Emin .+ xPhys.^penal*(E0 .-Emin)).*qe[i,j]));
                    dQ[i,j] = penal*(E0-Emin)*xPhys.^(penal-1).*qe[i,j];
                end
            end
            if optType=="bulk"
                #bulk
                c = -(Q[1,1]+Q[2,2]+Q[1,2]+Q[2,1]);
                dc = -(dQ[1,1]+dQ[2,2]+dQ[1,2]+dQ[2,1]);
            elseif optType=="shear"
                #shear
                c=-Q[3,3];
                dc=-dQ[3,3];
            elseif optType=="poisson"
                c = Q[1,2]-(0.8^loop)*(Q[1,1]+Q[2,2]);
                dc = dQ[1,2]-(0.8^loop)*(dQ[1,1]+dQ[2,2]);
            end
            
            dv = ones(nely,nelx);
            ## FILTERING/MODIFICATION OF SENSITIVITIES
            if ft == 1
                dc[:] = H*(x[:].*dc[:])./Hs./max.(1e-3,x[:]);
            elseif ft == 2
                dc[:] = H*(dc[:]./Hs);
                dv[:] = H*(dv[:]./Hs);
            end
            ## OPTIMALITY CRITERIA UPDATE OF DESIGN VARIABLES AND PHYSICAL DENSITIES
                
            if optType=="poisson"
                l1=0; l2=1e9; move = 0.1;
            else
                l1 =0; l2 = 1e9; move = 0.2;
            end
            while (l2-l1 > 1e-9)
                lmid = 0.5*(l2+l1);
                if optType=="poisson"
                    xnew = max.(0,max.(x.-move,min.(1.0,min.(x.+move,x.*(-dc./dv./lmid)))));
                else
                    xnew =max.(0.0,max.(x.-move,min.(1.0,min.(x.+move,x.*sqrt.(0.0.-dc./dv./lmid)))));
                end
                if ft == 1
                    xPhys = copy(xnew);
                elseif ft == 2
                    xPhys[:] = (H*xnew[:])./Hs;
                end
                if mean(xPhys[:]) > volfrac
                    l1 = lmid;
                else
                    l2 = lmid;
                end
            end
            change = maximum(abs.(xnew[:].-x[:]))
            x = xnew;
            ## PRINT RESULTS
            display(" It:$loop Obj:$c Vol:$(mean(xPhys[:])) ch:$change ")
    
            ## PLOT DENSITIES
            heatmap(xPhys, aspect_ratio=:equal, legend=false, axis=nothing, foreground_color_subplot=colorant"white",fc=:grays,clims=(0.0, 1.0))
            frame(anim)
        end
        return xnew
    end
    
    
    #####################################FEA KE####################################################################
    
    function lk()
        E=1
        nu=0.3
        k=[1/2-nu/6,1/8+nu/8,-1/4-nu/12,-1/8+3*nu/8,-1/4+nu/12,-1/8-nu/8,nu/6,1/8-3*nu/8]
        KE = E/(1-nu^2)*[  k[0+1] k[1+1] k[2+1] k[3+1] k[4+1] k[5+1] k[6+1] k[7+1];
                           k[1+1] k[0+1] k[7+1] k[6+1] k[5+1] k[4+1] k[3+1] k[2+1];
                           k[2+1] k[7+1] k[0+1] k[5+1] k[6+1] k[3+1] k[4+1] k[1+1];
                           k[3+1] k[6+1] k[5+1] k[0+1] k[7+1] k[2+1] k[1+1] k[4+1];
                           k[4+1] k[5+1] k[6+1] k[7+1] k[0+1] k[1+1] k[2+1] k[3+1];
                           k[5+1] k[4+1] k[3+1] k[2+1] k[1+1] k[0+1] k[7+1] k[6+1];
                           k[6+1] k[3+1] k[4+1] k[1+1] k[2+1] k[7+1] k[0+1] k[5+1];
                           k[7+1] k[2+1] k[1+1] k[4+1] k[3+1] k[6+1] k[5+1] k[0+1] ];
        return (KE)
    end
    
    function 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'];
    
        return KE
    end
    
    
    function make_filter(nelx,nely,rmin)
        iH = ones(convert(Int,nelx*nely*(2*(ceil(rmin)-1)+1)^2),1)
        jH = ones(Int,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(vec(iH),vec(jH),vec(sH))
        Hs = sum(H,dims=2)
        return H,Hs
    end
    
    function make_filter3D(nelx,nely,nelz,rmin)
        iH=[]
        jH=[]
        sH=[]
        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;
                                append!(iH, e1  )
                                append!(jH, e2  )
                                append!(sH, max(0.0,rmin-sqrt((i1-i2)^2+(j1-j2)^2+(k1-k2)^2) ))
                                
                            end
                        end
                    end
                end
            end
        end
        iH=reshape(iH,length(iH),1)
        jH=reshape(jH,length(jH),1)
        sH=reshape(convert(Array{Float64}, sH),length(sH),1)
        H = sparse(vec(iH),vec(jH),vec(sH))
        Hs = sum(H,dims=2)
        return H,Hs
    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=zeros(4,8)
                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: 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;
        # display(L)
        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,3) zeros(3,3);zeros(3,3) inv(J) zeros(3,3);zeros(3,3) zeros(3,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;
                    # display(dN)
                    # display(G)
                    
                    Be = L*G*dN;
                    Ke = Ke + GaussWeigh[ii]*GaussWeigh[jj]*GaussWeigh[kk]*det(J)*(Be'*DH*Be);
                end
            end
        end
        return Ke
    end
    
    ######### ELEMENT AND NODE NUMBERING IN 3D MESH 
    function get_num(nx, ny, nz, i, j, k)
        num = (nx*ny)*(k-1) + nx*(j-1) + i;
        return num
    end
    
    ######### GLOBAL DOFS FOR A GIVEN ELEMENT 
    function  get_elem_dofs(nnx, nny, nnz, elx, ely, elz)
        n = get_num(nnx, nny, nnz, elx, ely, elz);
        N = [n; n+1; n+nnx+1; n+nnx; n+nnx*nny; n+nnx*nny+1; n+nnx*nny+nnx+1; n+nnx*nny+nnx];
        dofs = zeros(Int,24); 
        for j = 1:8; 
            for i = 1:3; 
                dofs[3*(j-1)+i] = Int(3*(N[j]-1)+i); 
            end
        end
        return dofs
    end
    
    function getDisplacement(xPhys,nelx,nely,nelz,getProblem)
        
    
        
        # Max and min stiffness
        Emin=1e-9
        Emax=1.0
        nu=0.3
        # dofs:
        ndof = 3*(nelx+1)*(nely+1)*(nelz+1)
        # Allocate design variables (as array), initialize and allocate sens.
        x=volfrac * ones(Float64,nely,nelx,nelz)
        xold=copy(x)
        
        
        g=0 # must be initialized to use the NGuyen/Paulino OC approach
        dc=zeros(Float64,(nely,nelx,nelz))
        
        # FE: Build the index vectors for the for coo matrix format.
        KE=lk_H8(nu)
        nele = nelx*nely*nelz
        
        nodenrs = reshape(1:(1+nelx)*(1+nely)*(1+nelz),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 = repeat(edofVec,1,24).+repeat([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]],nelx*nely*nelz,1)
            
        iK = convert(Array{Int},reshape(kron(edofMat,ones(24,1))',24*24*nele,1))
        jK = convert(Array{Int},reshape(kron(edofMat,ones(1,24))',24*24*nele,1))
        
    
    
        # # USER-DEFINED LOAD DOFs
        # il = [0 nelx]; jl = [nely nely]; kl = [0 0];
        # loadnid = kl .*(nelx+1) .*(nely+1) .+il .*(nely .+1) .+(nely+1 .-jl);
        # loaddof = 3 .*loadnid[:] .- 2;
        # din = loaddof[1]; dout = loaddof[2];
        # F = sparse(loaddof,[1;2],[1;-1],ndof,2);
    
        # # USER-DEFINED SUPPORT FIXED DOFs
        # # Top face
        # m = Matlab.meshgrid(0:nelx,0:nelz)
        # iif=m[1]
        # kf=m[2]
        # fixednid = kf .*(nelx+1) .*(nely+1) .+iif .*(nely+1) .+1;
        # fixeddof_t = 3 .*fixednid[:] .-1;
        # # Side face
        # m = Matlab.meshgrid(0:nelx,0:nely)
        # iif=m[1]
        # jf=m[2]
        # fixednid = iif .*(nely+1) .+(nely+1 .-jf);
        # fixeddof_s = 3*fixednid[:];
        # # Two pins
        # iif = [0;0]; jf = [0;1]; kf = [nelz;nelz];
        # fixednid = kf .*(nelx+1) .*(nely .+1) .+iif .*(nely .+1) .+(nely+1 .-jf)
        # fixeddof_p = [3 .*fixednid[:]; 3 .*fixednid[:].-1; 3 .*fixednid[:].-2] # DOFs
        # # Fixed DOFs
        # fixeddof = union(fixeddof_t,fixeddof_s);
        # fixeddof = union(fixeddof, fixeddof_p);
        # fixeddof = sort(fixeddof);
        
        # # Displacement vector
        # U = zeros(ndof,2);
        # freedofs = setdiff(1:ndof,fixeddof)
    
        U,F,freedofs,din,dout=getProblem(nelx,nely,nelz)
    
    
        iH=[]
        jH=[]
        sH=[]
        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;
                                append!(iH, e1  )
                                append!(jH, e2  )
                                append!(sH, max(0.0,rmin-sqrt((i1-i2)^2+(j1-j2)^2+(k1-k2)^2) ))
                                
                            end
                        end
                    end
                end
            end
        end
    
        iH=reshape(iH,length(iH),1)
        jH=reshape(jH,length(jH),1)
        sH=reshape(convert(Array{Float64}, sH),length(sH),1)
        H = sparse(vec(iH),vec(jH),vec(sH))
        Hs = sum(H,dims=2)
        ###################################################
    
    
        # FE-ANALYSIS
        sK = reshape(KE[:]*(Emin.+xPhys[:]'.^penal*(Emax-Emin)),24*24*nelx*nely*nelz,1)
        K = sparse(vec(iK),vec(jK),vec(sK)) 
        K[din,din] = K[din,din] + 0.1
        K[dout,dout] = K[dout,dout] + 0.1
        K = (K+K')/2
    
    
        @timed U[freedofs,:] = K[freedofs,freedofs] \ Array(F[freedofs,:])
    
        return U,ndof,freedofs
    end
    
    #####################################Ployt####################################################################
    function topplot3d(xPhys)
        ix=[]
        iy=[]
        iz=[]
        for j in 1:nely
            for i in 1:nelx
                for k in 1:nelz
                    if(xPhys[j,i,k]>0.0)
                        append!(ix,i)
                        append!(iy,j)
                        append!(iz,k)
                    end
                end
            end
        end
        # r = 4.0
        # lim = FRect3D((-4,-4,-4*r),(8,8,8*r))
    
        return scatter(ix,iz,iy,color="black",label="",markersize =4, aspect_ratio=:equal,markerstrokealpha = 0.2,markeralpha = 0.6,markershape = :square,camera = (30, 60),xlim=(0,nelx),zlim=(0,nely),ylim=(-10,10))#,markershape = :square
    
    function plotDisplacement(nelx,nely,nelz,xPhysC,getProblem=inverter,factor=0.04,cameraX=30,cameraY=60)
        U,ndof,freedofs=getDisplacement(xPhysC,nelx,nely,nelz,getProblem)
        displacement=reshape((U[:,2]),3,(nely+1),(nelx+1),(nelz+1));
    
    
        anim1=Animation()
    
        for step in 0:10
    
            exg=factor*step
    
            for j in 1:nely
                for i in 1:nelx
                    for k in 1:nelz
                        if(xPhysC[j,i,k]>0.0)
    
                            append!(ix,i+exg*(displacement[1,j,i,k]))
                            append!(iy,j+exg*(displacement[2,j,i,k]))
                            append!(iz,k+exg*(displacement[3,j,i,k]))
    
                        end
                    end
                end
            end
            # r = 4.0
            # lim = FRect3D((-4,-4,-4*r),(8,8,8*r))
    
            scatter(ix,iz,iy,color="black",label="",markersize =4, aspect_ratio=:equal,markerstrokealpha = 0.2,markeralpha = 0.6,markershape = :square,camera = (cameraX,cameraY),xlim=(0,nelx*1.5),zlim=(-0.5*nely,nely*1.5),ylim=(-10,10))#,markershape = :square
    
            frame(anim1)
        end
        return anim1
        
    end
    
    function make_bitmap(p,nx,ny,alpha)
        color = [1 0 0; 0 0 .45; 0 1 0; 0 0 0; 1 1 1];
        I = zeros(nx*ny,3);
        for j = 1:p
            I[:,1:3] = I[:,1:3] + alpha[:,j] .*color[j,1:3]';
        end
        # I = imresize(reshape(I,ny,nx,3),10,'bilinear');
        I=reshape(I,ny,nx,3)
        II=hcat(I[:,end:-1:1,:],I)
        return II
    end
    
    function make_bitmap_compliant(p,nx,ny,alpha)
        color = [1 0 0; 0 0 .45; 0 1 0; 0 0 0; 1 1 1];
        I = zeros(nx*ny,3);
        for j = 1:p
            I[:,1:3] = I[:,1:3] + alpha[:,j] .*color[j,1:3]';
        end
        # I = imresize(reshape(I,ny,nx,3),10,'bilinear');
        I=reshape(I,ny,nx,3)
        # II=hcat(I[:,end:-1:1,:],I)
        II=vcat(I[end:-1:1,:,:],I)
        return II
    end
    
    function make_bitmap_3d(p,nx,ny,nz,alpha)
        color = [1 0 0; 0 0 1; 0 1 0; 0 0 0; 1 1 1];
        I = zeros(nx*ny*nz,3);
        for j = 1:p
            I[:,1:3] = I[:,1:3] + alpha[:,j] .*color[j,1:3]';
        end
        # I = imresize(reshape(I,ny,nx,3),10,'bilinear');
        I=reshape(I,ny,nx,nz,3)
        II=hcat(I[:,end:-1:1,:,:],I)
        return II
    end
    
    function topplotmulti3d(nelx,nely,nelz,I,threshold)
        ixr=[]
        iyr=[]
        izr=[]
        
        ixg=[]
        iyg=[]
        izg=[]
        
        ixb=[]
        iyb=[]
        izb=[]
        for j in 1:nely
            for i in 1:nelx
                for k in 1:nelz
                    if(I[j,i,k,1]>threshold)
                        append!(ixr,i)
                        append!(iyr,j)
                        append!(izr,k)
                    end
                    if(I[j,i,k,2]>threshold)
                        append!(ixg,i)
                        append!(iyg,j)
                        append!(izg,k)
                    end
                    if(I[j,i,k,3]>threshold)
                        append!(ixb,i)
                        append!(iyb,j)
                        append!(izb,k)
                    end
                end
            end
        end
    
        p=scatter(ixr,izr,iyr,color="red",label="",markersize =4, aspect_ratio=:equal,markerstrokealpha = 0.2,markeralpha = 0.6,markershape = :square,camera = (30, 60),xlim=(0,nelx),zlim=(0,nely),ylim=(-10,10))#,markershape = :square
        p=scatter!(ixg,izg,iyg,color="green",label="",markersize =4, aspect_ratio=:equal,markerstrokealpha = 0.2,markeralpha = 0.6,markershape = :square,camera = (30, 60),xlim=(0,nelx),zlim=(0,nely),ylim=(-10,10))#,markershape = :square
        p=scatter!(ixb,izb,iyb,color="blue",label="",markersize =4, aspect_ratio=:equal,markerstrokealpha = 0.2,markeralpha = 0.6,markershape = :square,camera = (30, 60),xlim=(0,nelx),zlim=(0,nely),ylim=(-10,10))#,markershape = :square
    
        return p
    
    end
    
    function topplotmulti3d_mirror(nelx,nely,nelz,I,threshold,vertical)
        ixr=[]
        iyr=[]
        izr=[]
        
        ixg=[]
        iyg=[]
        izg=[]
        
        ixb=[]
        iyb=[]
        izb=[]
        if(vertical)
            for j in 1:nely
                for i in 1:nelx
                    for k in 1:nelz
                        if(I[j,i,k,1]>threshold)
                            append!(ixr,i)
                            append!(ixr,i)
                            append!(iyr,nely-j)
                            append!(iyr,j+nely-1)
                            append!(izr,k)
                            append!(izr,k)
                        end
                        if(I[j,i,k,2]>threshold)
                            append!(ixg,i)
                            append!(ixg,i)
                            append!(iyg,nely-j)
                            append!(iyg,j+nely-1)
                            append!(izg,k)
                            append!(izg,k)
                        end
                        if(I[j,i,k,3]>threshold)
                            append!(ixb,i)
                            append!(ixb,i)
                            append!(iyb,nely-j)
                            append!(iyb,j+nely-1)
                            append!(izb,k)
                            append!(izb,k)
                        end
                    end
                end
            end
        else
            for j in 1:nely
                for i in 1:nelx
                    for k in 1:nelz
                        if(I[j,i,k,1]>threshold)
                            append!(ixr,nelx-i+nelx-1)
                            append!(ixr,i)
                            append!(iyr,j)
                            append!(izr,k)
                            append!(iyr,j)
                            append!(izr,k)
                        end
                        if(I[j,i,k,2]>threshold)
                            append!(ixg,nelx-i+nelx-1)
                            append!(ixg,i)
                            append!(iyg,j)