Skip to content
Snippets Groups Projects
minimum_compliance.jl 7.88 KiB
Newer Older
Amira Abdel-Rahman's avatar
Amira Abdel-Rahman committed

# Amira Abdel-Rahman
# (c) Massachusetts Institute of Technology 2020 

function getDataFromSetup3D(setup,scale)
    # -----------------------------------------------------------------------
    # A(nel,1)        = cross-sectional area of elements
    # E(nel,1)        = Young's modulus of elements
    # f(ndf,nnp)      = prescribed nodal forces
    # g(ndf,nnp)      = prescribed nodal displacements
    # idb(ndf,nnp)    = 1 if the degree of freedom is prescribed, 0 otherwise
    # ien(nen,nel)    = element connectivities
    # ndf             = number of degrees of freedom per node
    # nel             = number of elements
    # nen             = number of element equations
    # nnp             = number of nodes
    # nsd             = number of spacial dimensions
    # xn(nsd,nnp)     = nodal coordinates

    # =======================================================================
    nodes=setup["nodes"]
    edges=setup["edges"]


    # ---- MESH -------------------------------------------------------------
    nsd =  3;  # number of spacial dimensions
    ndf =  3;  # number of degrees of freedom per node 
    nen =  2;  # number of element nodes

    nel =  length(edges);  # number of elements 
    nnp =  length(nodes);  # number of nodal points


    # ---- NODAL COORDINATES ------------------------------------------------
    # xn(i,N) = coordinate i for node N
    # N = 1,...,nnp
    # i = 1,...,nsd
    # -----------------------------------------------------------------------

    xn         = zeros(nsd,nnp);
    for i in 1:nnp
        xn[1:3, i]  = [(nodes[i]["position"]["x"]/scale)  (nodes[i]["position"]["y"]/scale) (nodes[i]["position"]["z"]/scale)]';
    end
    

    # ---- NODAL COORDINATES ------------------------------------------------
    # ien(a,e) = N
    # N: global node number - N = 1,...,nnp
    # e: element number     - e = 1,...,nel
    # a: local node number  - a = 1,...,nen
    # -----------------------------------------------------------------------

    ien = zeros(nen,nel);
    for i in 1:nel
        ien[1:2,i]  = [(edges[i]["source"]+1)   (edges[i]["target"]+1)]' ;
    end


    len=zeros(nel);
    for i in 1:nel
        x1=(nodes[(edges[i]["source"]+1)]["position"]["x"]/scale)
        x2=(nodes[(edges[i]["target"]+1)]["position"]["x"]/scale)

        y1=(nodes[(edges[i]["source"]+1)]["position"]["y"]/scale)
        y2=(nodes[(edges[i]["target"]+1)]["position"]["y"]/scale)

        z1=(nodes[(edges[i]["source"]+1)]["position"]["z"]/scale)
        z2=(nodes[(edges[i]["target"]+1)]["position"]["z"]/scale)

        len[i]  = sqrt((x1-x2)^2+(y1-y2)^2+(z1-z2)^2);
    end
    

    # ---- MATERIAL PROPERTIES ----------------------------------------------
    # E(e) = E_mat
    # e: element number     - e = 1,...,nel
    # -----------------------------------------------------------------------
    E_mat = 29000*1000;         # Young's modulus # lbf/in^2
    E = E_mat*ones(nel,1);
    # todo change to make it parameter

    # ---- GEOMETRIC PROPERTIES ---------------------------------------------
    # A(e) = A_bar
    # e: element number     - e = 1,...,nel
    # -----------------------------------------------------------------------
    #A = ones(nel);
    #A[:] .= 400; # mm^2

    # ---- BOUNDARY CONDITIONS ----------------------------------------------
    # prescribed displacement flags (essential boundary condition)
    #
    # idb(i,N) = 1 if the degree of freedom i of the node N is prescribed
    #          = 0 otherwise
    #
    # 1) initialize idb to 0
    # 2) enter the flag for prescribed displacement boundary conditions
    # -----------------------------------------------------------------------
    idb = zeros(ndf,nnp);
    for i in 1:nnp
        if nodes[i]["restrained_degrees_of_freedom"][1]
            idb[1,i]=1; 
        end
        if nodes[i]["restrained_degrees_of_freedom"][2]
            idb[2,i]=1; 
        end
        if nodes[i]["restrained_degrees_of_freedom"][3]
            idb[3,i]=1; 
        end
    end

    


    # ---- BOUNDARY CONDITIONS: PRESCRIBED NODAL DISPLACEMENTS --------------
    # g(i,N) = prescribed displacement magnitude
    # N = 1,...,nnp
    # i = 1,...,nsd
    #
    # 1) initialize g to 0
    # 2) enter the values
    # -----------------------------------------------------------------------
    g = zeros(ndf,nnp);


    # ---- BOUNDARY CONDITIONS: PRESCRIBED NODAL FORCES ---------------------
    # f(i,N) = prescribed force magnitude
    # N = 1,...,nnp
    # i = 1,...,nsd
    #
    # 1) initialize f to 0
    # 2) enter the values
    # -----------------------------------------------------------------------
    P = 20.0* 1000;     # lbf
    f = zeros(ndf,nnp);
    for i in 1:nnp
        f[1,i] = nodes[i]["force"]["x"]*P;
        f[2,i] = nodes[i]["force"]["y"]*P;
        f[3,i] = nodes[i]["force"]["z"]*P;
    end
    
    A=ones(nel)
    
    # ---- NUMBER THE EQUATIONS ---------------------------------------------
    # line 380
    id,neq = number_eq(idb,ndf,nnp);
    


    # ---- FORM THE ELEMENT STIFFNESS MATRICES ------------------------------
    # line 324
    nee = ndf*nen;                   # number of element equations
    
    Ke  = zeros(nee,nee,nel);
    Te  = zeros(nen*1,nen*nsd,nel);  # *1 is specific to truss
    for i = 1:nel
        Ke[:,:,i],Te[:,:,i] = Ke_truss(A[i],E[i],ien[:,i],nee,nsd,xn);
    end    

    return E,f,g,idb,ien,ndf,nel,nen,nnp,nsd,xn,len,Ke,Te
end
# =======================================================================

function getSensitivites(Ke0,dcomp,ien,nel,len)
    dfdA=zeros(nel)
    dgdA=zeros(nel)

    for i in 1:nel
        de=[dcomp[1,Int(ien[1,i])],dcomp[2,Int(ien[1,i])],dcomp[3,Int(ien[1,i])] ,dcomp[1,Int(ien[2,i])] ,dcomp[2,Int(ien[2,i])] ,dcomp[3,Int(ien[2,i])]]
        # println(de)
        # println(Ke0[:,:,i])
        dKedA=Ke0[:,:,i]
        dfdA[i]=(-1.0 .*de)'*dKedA*de
        dgdA[i]=len[i]
    end
    return dfdA,dgdA
end

# =======================================================================
function getSensitivitesFinite(nel,epsilon,len)
    dfdA=zeros(nel)
    dgdA=zeros(nel)
    A1 = ones(nel)
    A1[:] .= 0.25;
    Ke,K,F,d,ien,xn,stress,dcomp,g=FEM_truss(data_truss2,A1);
    for i in 1:nel
        A[:] .= 0.25; # mm^2
        A[i]=0.25+epsilon
        Ke,Kee,Fe,de,ien,xn,stress,dcomp,g=FEM_truss(data_truss2,A);
        Fx=F'*d -d'*K*d +d'*F
        Fxe=Fe'*de - de'*Kee*de + de'*Fe
        dfdA[i]=(Fxe[1] - Fx[1])/epsilon

        dgdA[i]=((sum(A .* len ) - 480) - (sum(A1 .* len ) - 480))/epsilon
    end
    return dfdA,dgdA
end


# =======================================================================


function optimizeTruss(problem,totalVolFactor,maxeval=500)
    
    E,f,g,idb,ien,ndf,nel,nen,nnp,nsd,xn,len,Ke,Te=problem
    
    nel=length(len)
    
    function FA(x::Vector, grad::Vector)

        K,F,d,stress,dcomp,g=FEM_truss(problem,x);
        # display(F)

        grad[:] .=getSensitivites(Ke,dcomp,ien,nel,len)[1]

        Fx=F'*d -d'*K*d +d'*F

        return Fx[1]
    end
    function FASIMP(x::Vector, grad::Vector)
        print("hena")

        K,F,d,stress,dcomp,g=FEM_frame(problem,x.^η);
        # display(F)

        grad[:] .=getSensitivitesSIMP(Ke0,dcomp,ien,nel,len,η,x)[1]

        Fx=F'*d -d'*K*d +d'*F

        return Fx[1]
    end

    function G(x::Vector, grad::Vector)
        grad[:] .=len[:]

        return (sum(x .* len ) - totalVolFactor)
    end
    FA(ones(nel)*totalVolFactor, fill(0.25,nel))
    G(ones(nel)*totalVolFactor, fill(0.25,nel))

    opt = Opt(:LD_MMA, nel)
    opt.lower_bounds = fill(1e-3,nel)
    opt.xtol_rel = 0.00001
    opt.maxeval = maxeval

    opt.min_objective = FA
    inequality_constraint!(opt, (x,gg) -> G(x,gg), 1e-6)

    display(@time (minf,minx,ret) = optimize(opt, ones(nel)))
    numevals = opt.numevals # the number of function evaluations
    display("got $minf after $numevals iterations (returned $ret)")
    
    return minx
end
# =======================================================================