Natural frequency analysis of 3d frame structure

License is MIT: see https://github.com/JuliaFEM/JuliaFEM.jl/blob/master/LICENSE.md

Natural frequency analysis of 3d frame structure

For general information about Euler-Bernoulli beam theory, see this wikipedia page. The model is a 3d frame, shown in picture.

using JuliaFEM, LinearAlgebra

Reading mesh

datadir = Pkg.dir("JuliaFEM", "examples", "3d_frame")
mesh = aster_read_mesh(joinpath(datadir, "model.med"))
println("Number of nodes in a model: ", length(mesh.nodes))

Create beam elements. For 3d model, we need to define at least Young's modulus, shear modulus, density cross-section area, moment of inertia in local coordinate system and polar moment of inertia.

beam_elements = create_elements(mesh, "FRAME")
@info("Number of elements: ", length(beam_elements))
update!(beam_elements, "youngs modulus", 210.0e6)
update!(beam_elements, "shear modulus", 84.0e6)
update!(beam_elements, "density", 7850.0e-3)
update!(beam_elements, "cross-section area", 20.0e-2)
update!(beam_elements, "torsional moment of inertia 1", 10.0e-5)
update!(beam_elements, "torsional moment of inertia 2", 10.0e-5)
update!(beam_elements, "polar moment of inertia", 30.0e-5)

The direction of beam is defined in same way than in ABAQUS. That is, we have a tangent direction and one normal direction. The third direction is then cross product of tangent and normal. Because the second area moment is same in both directions, we can choose normal direction freely.

for element in beam_elements
    X1, X2 = element("geometry", 0.0)
    t = (X2-X1)/norm(X2-X1)
    I = [1.0 0.0 0.0; 0.0 1.0 0.0; 0.0 0.0 1.0]
    k = indmax([norm(cross(t, I[:,k])) for k in 1:3])
    n = cross(t, I[:,k])/norm(cross(t, I[:,k]))
    update!(element, "normal", n)
end

Create boundary conditions: fix all degrees of freedom for nodes in a set FIXED. Here we first create elements of type Poi1 for each node j in set FIXED, update geometry field and then create new fields fixed displacmeent 1, fixed displacement 2, and so on, where the displacement / rotation is prescribed.

bc_elements = [Element(Poi1, [j]) for j in mesh.node_sets[:FIXED]]
update!(bc_elements, "geometry", mesh.nodes)
for i=1:3
    update!(bc_elements, "fixed displacement $i", 0.0)
    update!(bc_elements, "fixed rotation $i", 0.0)
end

Create a problem, containing beam elements and boundary conditions:

frame = Problem(Beam, "3d frame", 6)
add_elements!(frame, beam_elements)
add_elements!(frame, bc_elements)

Perform modal analysis

analysis = Analysis(Modal)
xdmf = Xdmf(joinpath(datadir, "3d_frame_results"); overwrite=true)
add_results_writer!(analysis, xdmf)
add_problems!(analysis, frame)
run!(analysis)
close(xdmf)

Each Analysis can have properties, e.g. time, maximum number of iterations, convergence tolerance and so on. Eigenvalues of calculation are stored as a properties of analysis:

freqs = sqrt.(step.properties.eigvals) / (2*pi)
println("Natural frequencies [Hz]: $(round.(freqs, 2))")

mode5

This page was generated using Literate.jl.