Skip to content

Using a BESO like algorithm

Eduardo Lenz edited this page Dec 10, 2024 · 3 revisions

The manuscript Zhi Hao Zuo, Yi Min Xie, A simple and compact Python code for complex 3D topology optimization, 2015, proposes a very simple algorithm to account for discrete values of relative density. The complete computer code using LFEM and LFilter is

#
# Min C(x)
# S.t
#      V(x)≤V̄
#
#      x = xmin OR x = 1
#

using LinearAlgebra, ProgressMeter
using BMesh, LMesh, TMeshes, LFEM
using LFilter


function main(vf=0.3,output="topo_beso.sol")

    Load the problem
    nx = 40*2
    ny = 25*2
    Lx = 8.0
    Ly = 5.0
    mesh = Cantilever_beam_bottom2D(nx,ny,:solid2D)

    # It just makes sense to filter if not using truss
    Get_eclass(mesh)==:solid || throw("main:: this example is for :solid2D or :solid3D elements")
    
    # Element size
    te = max(Lx/nx,Ly/ny)

    # Filter
    filter = Filter(mesh,3*te)

    # Material parametrization and derivative
    kparam(xe::Float64,p=3.0)=xe^p
    dkparam(xe::Float64,p=3.0)=p*xe^(p-1)

    # BESO parameters

    # Evolution rate
    er = 0.01

    # Number of iterations
    niter = 150

    # Number of elements
    ne = Get_ne(mesh)

    # Initial point
    ρ = ones(ne)
   
    # Volume of each element
    V = Volumes(mesh,ones(ne))

    # Total volume
    volume_full = sum(V)

    # Target volume
    Vast = vf*volume_full

    # Sensitivity index in the last iteration
    ESED_F_ANT = zeros(ne)

    # Main loop
     for j=1:niter

        # Actual volume
        volume_actual = sum.*V)

        # Volume for this iteration
        if volume_actual > Vast
           vol = max(Vast, volume_actual*(1.0 - er))
        elseif volume_actual < Vast
           vol = min(Vast,volume_actual*(1 + er))
        else
            vol = Vast
        end
        
        # Equilibrium
        U,F,_ = Solve_linear(mesh,ρ,kparam)

        # Sensitivity index for Compliance
        dC = Sensitivity_index(mesh,U,ρ,dkparam)

        # ESED
        SN = dC ./ V
        
        # Filter the ESEDs
        ESED_F =  LFilter.x2ρ(SN,filter)

        # Mean value using the last iteration
        ESED_F_media = (ESED_F .+ ESED_F_ANT)./2

        # Store the value for the next iteration
        ESED_F_ANT .= ESED_F_media 

        # Update the relative densities
        ρ = BESO(ρ, ESED_F_media, vol, V)
        

    end #j 

    # Write solution
    Gmsh_init(output,mesh)

    # Write topology
    Gmsh_element_scalar(mesh,ρ,output,"Topology")

   
end

#
# Volume
#
function Volumes(mesh::Mesh,x::Vector)
   
    
    # Number of elements
    ne = Get_ne(mesh)

    # Output vector
    V = zeros(ne)

    # Loop for all elements
    for ele in mesh
        
        # Volume of this element
        vol = Volume_element(mesh,ele)

        # Add to the total volume
        V[ele] =  vol*x[ele]
        
    end #ele
    
    return V
    
end


#
# Sensitivity index - Compliance
#
function Sensitivity_index(mesh::Mesh,U::Vector,x::Vector,dkparam::Function)
    
    # Number of elements
    ne = Get_ne(mesh)

    # Output vector
    D = zeros(ne)

    # Loop over elements in the mesh
    for ele in mesh

        # Dofs
        dofs = DOFs(mesh,ele)
   
        # Element displacement 
        ul = U[dofs] 

        # Element stiffness 
        Ke = Local_K(mesh,ele)

        D[ele]  =  dkparam(x[ele])*dot(ul,Ke,ul)

    end
   
    return D

end


#
# BESO as in Zhi Hao Zuo, Yi Min Xie, A simple and compact Python code for complex 3D topology optimization, 2015
#
function BESO(x, D, Vlim, V, tol=1E-6, xmin=1E-3, xmax=1.0)

    # Limit values
    D_min = minimum(D)
    D_max = maximum(D)
 
    # Make a copy
    xn = copy(x)

    # Main loop (bisection)
    while (D_max - D_min)/D_max > tol

        # Threshold value
        corte = (D_min + D_max)/2 

        # Initialize the volume
        volume = 0.0

        # For each variable
        for i in LinearIndices(x)

            # Round down or up, relative to the threshold
            if D[i] < corte

                xn[i] = xmin  

            elseif D[i] > corte

                xn[i] = xmax 

            end #if

            # Add the volume
            volume += xn[i]*V[i]
        
        end #i

        # Bisection
        if volume > Vlim
            D_min = corte
        else
            D_max = corte
        end

    end # while

    # Return the new distribution of design variables
    return xn

end

Clone this wiki locally