Skip to content
Snippets Groups Projects
BeamFEM.jl 8.63 KiB
Newer Older
  • Learn to ignore specific revisions
  • Amira Abdel-Rahman's avatar
    Amira Abdel-Rahman committed
    # // Amira Abdel-Rahman
    # // (c) Massachusetts Institute of Technology 2020
    
    using LinearAlgebra
    import JSON
    
    
    function rotation_matrix(element_vector, x_axis, y_axis,z_axis)
        # find the direction cosines
        L=norm(element_vector)
        l = (element_vector[1])/L
    	m = (element_vector[2])/L
    	n = (element_vector[3])/L
    	D = ( l^2+ m^2+n^2)^0.5
        
        transMatrix=[[l m  n  0  0  0  0  0  0  0  0  0];[-m/D l/D  0  0  0  0  0  0  0  0  0  0];[ -l*n/D  -m*n/D  D  0  0  0  0  0  0  0  0  0];[ 0  0  0       l       m  n  0  0  0  0  0  0];[ 0  0  0    -m/D     l/D  0  0  0  0  0  0  0];[ 0  0  0  -l*n/D  -m*n/D  D  0  0  0  0  0  0];[ 0  0  0  0  0  0       l       m  n  0  0  0];[ 0  0  0  0  0  0    -m/D     l/D  0  0  0  0];[ 0  0  0  0  0  0  -l*n/D  -m*n/D  D  0  0  0];[ 0  0  0  0  0  0  0  0  0       l       m  n];[ 0  0  0  0  0  0  0  0  0    -m/D     l/D  0];[ 0  0  0  0  0  0  0  0  0  -l*n/D  -m*n/D  D]]
    	
        return transMatrix
    end
    
    function get_stresses(setup)
        nodes      = setup["nodes"]
        edges      = setup["edges"]
        ndofs      = length(nodes)*6
    
        x_axis     = [1 0 0]
        y_axis     = [0 1 0]
        z_axis     = [0 0 1]
    
        # find the stresses in each member
        stresses=zeros(length(edges))
        max11=-10e6
        min11=10e6
        for edge in edges
            #degrees_of_freedom = properties["degrees_of_freedom"]
    
            element=parse(Int,edge["id"][2:end])
    
            # find the nodes that the lements connects
            fromNode = nodes[edge["source"]+1]
            toNode = nodes[edge["target"]+1]
    
            # the coordinates for each node
            fromPoint = [fromNode["position"]["x"] fromNode["position"]["y"] fromNode["position"]["z"]]
            toPoint = [toNode["position"]["x"] toNode["position"]["y"] toNode["position"]["z"]]
    
            # find the degrees of freedom for each node
            dofs = convert(Array{Int}, fromNode["degrees_of_freedom"])
            dofs=vcat(dofs,convert(Array{Int}, toNode["degrees_of_freedom"]))
    
            element_vector=toPoint-fromPoint
           
    
            # find rotated mass and stifness matrices
            tau = rotation_matrix(element_vector, x_axis,y_axis,z_axis)
            
            # i1=parse(Int,fromNode["id"][2:end])
            # i2=parse(Int,toNode["id"][2:end])
            
            # global_displacements=[X[(i1)*6+1] X[(i1)*6+2] X[(i1)*6+3] X[(i1)*6+4] X[(i1)*6+5] X[(i1)*6+6] X[(i2)*6+1] X[(i2)*6+2] X[(i2)*6+3] X[(i2)*6+4] X[(i2)*6+5] X[(i2)*6+6]] # todo change
            global_displacements=[fromNode["displacement"]["x"] fromNode["displacement"]["y"] fromNode["displacement"]["z"] fromNode["angle"]["x"] fromNode["angle"]["y"] fromNode["angle"]["z"] toNode["displacement"]["x"] toNode["displacement"]["y"] toNode["displacement"]["z"] toNode["angle"]["x"] toNode["angle"]["y"] toNode["angle"]["z"]] # todo change
    
            # nodal displacement
    
            q=tau*transpose(global_displacements)
            # println(q)
            # calculate the strain and stresses
            strain =(q[7]-q[1])/norm(element_vector)
            E = edge["stiffness"]# youngs modulus
            stress=E.*strain
            edge["stress"]=stress
            if stress>max11
                max11=stress
            end
            if stress<min11
                min11=stress
            end
            # println(element)
            # println(stress)
        end
    
        
        
        setup["viz"]["minStress"]=min11
        setup["viz"]["maxStress"]=max11
        return stresses
    end
    
    function get_matrices(setup)
        
        nodes      = setup["nodes"]
        edges      = setup["edges"]
        ndofs      = length(nodes)*6
    
        x_axis     = [1 0 0]
        y_axis     = [0 1 0]
        z_axis     = [0 0 1]
    
        M = zeros((ndofs,ndofs))
        K = zeros((ndofs,ndofs))
    
        for edge in edges
            #degrees_of_freedom = properties["degrees_of_freedom"]
    
            element=parse(Int,edge["id"][2:end])
    
            # find the nodes that the lements connects
            fromNode = nodes[edge["source"]+1]
            toNode = nodes[edge["target"]+1]
    
            # the coordinates for each node
            fromPoint = [fromNode["position"]["x"] fromNode["position"]["y"] fromNode["position"]["z"]]
            toPoint = [toNode["position"]["x"] toNode["position"]["y"] toNode["position"]["z"]]
    
            # find the degrees of freedom for each node
            dofs = convert(Array{Int}, fromNode["degrees_of_freedom"])
            dofs=vcat(dofs,convert(Array{Int}, toNode["degrees_of_freedom"]))
    
            element_vector=toPoint-fromPoint
    
            # find element mass and stifness matrices
            length   = norm(element_vector)
            rho      = edge["density"]
            area     = edge["area"]
            E        = edge["stiffness"]# youngs modulus
    
            A = edge["area"]
            G=1.0#todo shear_modulus
            ixx = 1.0#todo section ixx
            iyy = 1.0#todo section.iyy#
            l0=length
            j=1.0;#todo check
            l02 = l0 * l0
            l03 = l0 * l0 * l0
    
            # Cm = rho * area * length /6.0
            # Ck= E * area / length 
    
            # m = [[2 1];[1 2]]
            # k = [[1 -1];[-1 1]]
    
            k = [[E*A/l0  0  0  0  0  0  -E*A/l0  0  0  0  0  0];[0  12*E*ixx/l03  0  0  0  6*E*ixx/l02  0  -12*E*ixx/l03  0  0  0  6*E*ixx/l02];[0  0  12*E*iyy/l03  0  -6*E*iyy/l02  0  0  0  -12*E*iyy/l03  0  -6*E*iyy/l02  0];[0  0  0  G*j/l0  0  0  0  0  0  -G*j/l0  0  0];[0  0  -6*E*iyy/l02  0  4*E*iyy/l0  0  0  0  6*E*iyy/l02  0  2*E*iyy/l0  0];[0  6*E*ixx/l02  0  0  0  4*E*ixx/l0  0  -6*E*ixx/l02  0  0  0  2*E*ixx/l0];[-E*A/l0  0  0  0  0  0  E*A/l0  0  0  0  0  0];[0  -12*E*ixx/l03  0  0  0  -6*E*ixx/l02  0  12*E*ixx/l03  0  0  0  -6*E*ixx/l02];[0  0  -12*E*iyy/l03  0  6*E*iyy/l02  0  0  0  12*E*iyy/l03  0  6*E*iyy/l02  0];[0  0  0  -G*j/l0  0  0  0  0  0  G*j/l0  0  0];[0  0  -6*E*iyy/l02  0  2*E*iyy/l0  0  0  0  6*E*iyy/l02  0  4*E*iyy/l0  0];[0  6*E*ixx/l02  0  0  0  2*E*ixx/l0  0  -6*E*ixx/l02  0  0  0  4*E*ixx/l0]]
    
            # find rotated mass and stifness matrices
            tau = rotation_matrix(element_vector, x_axis,y_axis,z_axis)
    
            # m_r=transpose(tau)*m*tau
            k_r=transpose(tau)*k*tau
    
    
            # change from element to global coordinate
            index= dofs.+1
    
            B=zeros((12,ndofs))
            for i in 1:12
                  B[i,index[i]]=1.0
            end
    
    
            # M_rG= transpose(B)*m_r*B
            K_rG= transpose(B)*k_r*B
    
            # M += Cm .* M_rG
            # K += Ck .* K_rG
            K +=  K_rG
    
        end
    
        # construct the force vector
        F=zeros(ndofs)
        remove_indices=[];
        for node in nodes
            #insert!(F,i, value);
            #F=vcat(F,value)
            i=parse(Int,node["id"][2:end])
            f=node["force"]
            # println(f)
            F[(i)*6+1]=f["x"]
            F[(i)*6+2]=f["y"]
            F[(i)*6+3]=f["z"]
            F[(i)*6+4]=0
            F[(i)*6+5]=0
            F[(i)*6+6]=0
            dofs = convert(Array{Int}, node["degrees_of_freedom"]).+1
            restrained_dofs=node["restrained_degrees_of_freedom"]
            for (index, value) in enumerate(dofs)
                if restrained_dofs[index]
                    append!( remove_indices, value)
                end
            end
        end
    
        # println(remove_indices)
        # print(K)
        # print(F)
    
        # M = M[setdiff(1:end, remove_indices), :]
        K = K[setdiff(1:end, remove_indices), :]
    
        # M = M[:,setdiff(1:end, remove_indices)]
        K = K[:,setdiff(1:end, remove_indices)]
    
        F = F[setdiff(1:end, remove_indices)]
        return M,K,F
    end
    
    function updateDisplacement(setup, X)
        nodes= setup["nodes"]
        i=0
        for node in nodes
            if !node["restrained_degrees_of_freedom"][1]
                #i=parse(Int,node["id"][2:end])
                node["displacement"]["x"]=X[(i)*6+1]
                node["displacement"]["y"]=X[(i)*6+2]
                node["displacement"]["z"]=X[(i)*6+3]
                node["angle"]["x"]=X[(i)*6+4]
                node["angle"]["y"]=X[(i)*6+5]
                node["angle"]["z"]=X[(i)*6+6]
                i=i+1
            end
        end
    end
    
    function solveFea(setup)
    	// # determine the global matrices
    	M,K,F=get_matrices(setup)
        
        #println(M)
        #println(K)
        #println(F)
        
        #evals=eigvals(K,M)
        #evecs=eigvecs(K,M)
        #frequencies=sqrt.(evals)
        X=inv(K)*F
        
        
        #updateDisplacement(displacements);
        updateDisplacement(setup, X)
        
        # determine the stresses in each element
        stresses=get_stresses(setup)
    
    end
    
    
    ###################
    ### Read data #####
    ###################
    setup = Dict()
    open("./json/setupChiral3.json", "r") do f
        global setup
        dicttxt = String(read(f))  # file information to string
        setup=JSON.parse(dicttxt)  # parse and transform data
    end
    
    setup=setup["setup"]
    
    
    ###################
    ### Solve FEA data #####
    ###################
    solveFea(setup)
    
    
    ###################
    ### Write data #####
    ###################
    
    # pass data as a json string (how it shall be displayed in a file)
    stringdata = JSON.json(setup)
    
    # write the file with the stringdata variable information
    open("./json/trialJulia.json", "w") do f
            write(f, stringdata)
         end