This file is a part of JuliaFEM. License is MIT: see https://github.com/JuliaFEM/JuliaFEM.jl/blob/master/LICENSE.md
JuliaFEM Linear Static Example
Preprocessing
using JuliaFEM
First we will read in the mesh. Geometry and mesh are greated with FreeCAD, where med format is selected for exporting. Mesh file consist also edge and surface mesh, which we will need to neglect later.
datadir = Pkg.dir("JuliaFEM", "examples", "linear_static")
meshfile = joinpath(datadir, "JuliaFEMSMP18.med")
mesh = aster_read_mesh(meshfile)
Next we will create the model and define Elasticity. Also elements are added to the model.
model = Problem(Elasticity, "OTHER", 3)
model_elements = create_elements(mesh, "OTHER")
Elements need material properties and they are defined next
update!(model_elements, "youngs modulus", 208.0E3)
update!(model_elements, "poissons ratio", 0.30)
update!(model_elements, "density", 7.80E-9)
add_elements!(model, model_elements)
We can ignore Seg3 and Tri6 elements using filter
with a special function returning true if element is something else than Seg3 or Tri6:
function is_not_Seg3_or_Tri6(element)
return !isa(element, Union{Element{Seg3}, Element{Tri6}})
end
filter!(is_not_Seg3_or_Tri6, model.elements)
0-element Array{Element,1}
The whole idea of the JuliaFEM input is to be a normal Julia script, where the user can freely define any functions needed to perform the task. Here we define a function, which finds nodes on the given plane yz, xz or xy from the given height.
function add_nodes_at_certain_plane_to_node_set!(mesh, name, vector_id, distance,
radius=6.0)
for (node, coords) in mesh.nodes
if isapprox(coords[vector_id], distance, atol=radius)
add_node_to_node_set!(mesh, name, node)
end
end
return nothing
end
add_nodes_at_certain_plane_to_node_set! (generic function with 2 methods)
We will find nodes from the xz-plane going through point (0,50,0) or actually we previously defined the radius to be 6.0, which means (0,[44,56],0). In other words we will select each node, which second coordinate value is between 44 and 56. This function will edit mesh object and add node set called :mid_fixed
to it.
add_nodes_at_certain_plane_to_node_set!(mesh, :mid_fixed, 2, 50.0)
We need to somehow handle the i's dot. I looked the rough coordinates of the dot in FreeCAD and now we can search three closest nodes to these coordinates. Those will be added to the same set :mid_fixed
.
ipoint = find_nearest_nodes(mesh, [165.0, 88.0, 10],3)
for poi in ipoint
add_node_to_node_set!(mesh, :mid_fixed, poi)
end
The fixed boundary conditions are defined next.
fixed = Problem(Dirichlet, "fixed", 3, "displacement")
fixed_elements = create_nodal_elements(mesh, "mid_fixed")
add_elements!(fixed, fixed_elements)
update!(fixed_elements, "displacement 1", 0.0)
update!(fixed_elements, "displacement 2", 0.0)
update!(fixed_elements, "displacement 3", 0.0)
Let's use simple acceleration load.
update!(model_elements, "displacement load 1", 1.0)
Finally the ´Analysis` couples everything togeter.
analysis = Analysis(Linear, model, fixed)
Analysis{Linear}("LinearSolver", Problem[Problem{Elasticity}("OTHER", 3, "none", Element[], Dict{Element,Array{Int64,1}}(), Assembly(SparseMatrixCOO{Float64}(Int64[], Int64[], Float64[]), SparseMatrixCOO{Float64}(Int64[], Int64[], Float64[]), SparseMatrixCOO{Float64}(Int64[], Int64[], Float64[]), SparseMatrixCOO{Float64}(Int64[], Int64[], Float64[]), SparseMatrixCOO{Float64}(Int64[], Int64[], Float64[]), SparseMatrixCOO{Float64}(Int64[], Int64[], Float64[]), SparseMatrixCOO{Float64}(Int64[], Int64[], Float64[]), SparseMatrixCOO{Float64}(Int64[], Int64[], Float64[]), SparseMatrixCOO{Float64}(Int64[], Int64[], Float64[]), SparseMatrixCOO{Float64}(Int64[], Int64[], Float64[]), Float64[], Float64[], Inf, Float64[], Float64[], Inf, Int64[]), Dict{String,AbstractField}(), String[], Elasticity(:continuum, false, false, Symbol[])), Problem{Dirichlet}("fixed", 3, "displacement", Element[], Dict{Element,Array{Int64,1}}(), Assembly(SparseMatrixCOO{Float64}(Int64[], Int64[], Float64[]), SparseMatrixCOO{Float64}(Int64[], Int64[], Float64[]), SparseMatrixCOO{Float64}(Int64[], Int64[], Float64[]), SparseMatrixCOO{Float64}(Int64[], Int64[], Float64[]), SparseMatrixCOO{Float64}(Int64[], Int64[], Float64[]), SparseMatrixCOO{Float64}(Int64[], Int64[], Float64[]), SparseMatrixCOO{Float64}(Int64[], Int64[], Float64[]), SparseMatrixCOO{Float64}(Int64[], Int64[], Float64[]), SparseMatrixCOO{Float64}(Int64[], Int64[], Float64[]), SparseMatrixCOO{Float64}(Int64[], Int64[], Float64[]), Float64[], Float64[], Inf, Float64[], Float64[], Inf, Int64[]), Dict{String,AbstractField}(), String[], Dirichlet(:incremental, false, false, 1))], Dict{String,AbstractField}(), AbstractResultsWriter[], Linear(0.0))
Let's write resuls to Xdmf file
xdmf = Xdmf("model_results"; overwrite=true)
add_results_writer!(analysis, xdmf)
This is how the stresses are requested
push!(model.postprocess_fields, "stress")
1-element Array{String,1}:
"stress"
Now we have all we need to run the analysis.
run!(analysis)
Postprocessing
In order to look the results, we will need to close the xdmf that it is actually written to the file from buffer.
close(xdmf)
Finally when we open the model in ParaView and set some settings we have this end result.
Testing
First let's test that we have the output files writen to the disk
if VERSION < v"1.0.0"
using Base.Test
else
using Test
end
@test isfile("model_results.xmf")
@test isfile("model_results.h5")
Secondly let's test that we have the same maximum displacement each time. This is also an usefull example how to access the displacements values.
time = 0.0
u = analysis("displacement", time)
u_norms = Dict(i => norm(j) for (i, j) in u)
@test isapprox(maximum(values(u_norms)),2.4052929896922337)
This page was generated using Literate.jl.