Use Gmsh to create model.
import Gmsh: gmsh
gmsh.initialize()
gmsh.option.setNumber("General.Terminal", 1)
gmsh.model.add("plate_with_hole")
lc = 0.5
gmsh.model.geo.addPoint(0.0, 0.0, 0.0, lc, 1)
gmsh.model.geo.addPoint(1.0, 0.0, 0.0, lc, 2)
gmsh.model.geo.addPoint(5.0, 0.0, 0.0, lc, 3)
gmsh.model.geo.addPoint(5.0, 5.0, 0.0, lc, 4)
gmsh.model.geo.addPoint(0.0, 5.0, 0.0, lc, 5)
gmsh.model.geo.addPoint(0.0, 1.0, 0.0, lc, 6)
gmsh.model.geo.addLine(2, 3, 1)
gmsh.model.geo.addLine(3, 4, 2)
gmsh.model.geo.addLine(4, 5, 3)
gmsh.model.geo.addLine(5, 6, 4)
gmsh.model.geo.addCircleArc(6, 1, 2, 5)
gmsh.model.geo.addCurveLoop([3, 4, 5, 1, 2], 1)
gmsh.model.geo.addPlaneSurface([1], 1)
gmsh.model.geo.extrude([(2,1)], 0, 0, 0.3)
gmsh.model.addPhysicalGroup(2, [19], 1)
gmsh.model.addPhysicalGroup(2, [31], 2)
gmsh.model.addPhysicalGroup(2, [15], 3)
gmsh.model.addPhysicalGroup(2, [27], 4)
gmsh.model.addPhysicalGroup(2, [32], 5)
gmsh.model.addPhysicalGroup(2, [1], 6)
gmsh.model.addPhysicalGroup(3, [1], 1)
gmsh.model.setPhysicalName(2, 1, "LEFT")
gmsh.model.setPhysicalName(2, 2, "RIGHT")
gmsh.model.setPhysicalName(2, 3, "TOP")
gmsh.model.setPhysicalName(2, 4, "DOWN")
gmsh.model.setPhysicalName(2, 5, "FRONT")
gmsh.model.setPhysicalName(2, 6, "BACK")
gmsh.model.setPhysicalName(3, 1, "PLATE")
gmsh.model.geo.synchronize()
gmsh.model.mesh.generate(3)
Nodes can be extracted using getNodes()
.
node_ids, node_coords, _ = gmsh.model.mesh.getNodes()
length(node_ids), length(node_coords)
node_ids[1:3], node_coords[1:9]
While it's not strictly necessary, let's create dictionary of nodes.
nodes = Dict(node_ids[i] => node_coords[3*(i-1)+1:3*(i-1)+3] for i=1:length(node_ids))
nodes
Next elements. For that, we extract physical groups and entities attached to them.
physical_groups = gmsh.model.getPhysicalGroups()
for (dim, tag) in physical_groups
entities = gmsh.model.getEntitiesForPhysicalGroup(dim, tag)
physical_name = gmsh.model.getPhysicalName(dim, tag)
println("($dim, $tag) => $physical_name, entities: ", join(entities, ", "))
end
For example, elements in set LEFT can be accessed using getElements
, where the first argument is dimension (2 = 2d), and the second argument is the tag of entity.
element_types, element_ids, element_connectivity = gmsh.model.mesh.getElements(2, 19)
element_types
for i in element_types
println("$i = ", gmsh.model.mesh.getElementProperties(i))
end
Like with nodes, let's create auxiliary dictionaries to make further processing of mesh easier.
left_elements = Dict(element_ids[1][i] => element_connectivity[1][3*(i-1)+1:3*(i-1)+3] for i=1:length(element_ids[1]))
We do the same thing for all physical groups. A small function is written to make task easier.
function elements_to_dict(dim, tag)
element_types, element_ids, element_connectivity = gmsh.model.mesh.getElements(dim, tag)
length(element_types) == 1 || error("Only one element type / entity supported.")
nelements = length(element_ids[1])
nnodes = length(element_connectivity[1]) ÷ nelements
elements = Dict(element_ids[1][i] => element_connectivity[1][nnodes*(i-1)+1:nnodes*i] for i=1:nelements)
end
right_elements = elements_to_dict(2, 31)
top_elements = elements_to_dict(2, 15)
down_elements = elements_to_dict(2, 27)
front_elements = elements_to_dict(2, 32)
back_elements = elements_to_dict(2, 1)
plate_elements = elements_to_dict(3, 1);
println("Number of nodes in model (total) = ", length(nodes))
println("Number of elements in physical group LEFT = ", length(left_elements))
println("Number of elements in physical group RIGHT = ", length(right_elements))
println("Number of elements in physical group TOP = ", length(top_elements))
println("Number of elements in physical group DOWN = ", length(down_elements))
println("Number of elements in physical group FRONT = ", length(front_elements))
println("Number of elements in physical group BACK = ", length(back_elements))
println("Number of elements in physical group PLATE = ", length(plate_elements))
Now the mesh data is in dictionaries. What is left, is to create Mesh
object and then build the model and run analysis.
using JuliaFEM
mesh = Mesh()
for (nid, ncoords) in nodes
add_node!(mesh, Int(nid), ncoords)
end
for (elid, elcon) in left_elements
add_element!(mesh, Int(elid), :Tri3, elcon)
add_element_to_element_set!(mesh, :LEFT, Int(elid))
end
function elements_to_mesh!(mesh, elements, eltype, set_name)
for (elid, elcon) in elements
add_element!(mesh, Int(elid), eltype, elcon)
add_element_to_element_set!(mesh, set_name, Int(elid))
end
end
elements_to_mesh!(mesh, right_elements, :Tri3, :RIGHT)
elements_to_mesh!(mesh, top_elements, :Tri3, :TOP)
elements_to_mesh!(mesh, down_elements, :Tri3, :DOWN)
elements_to_mesh!(mesh, front_elements, :Tri3, :FRONT)
elements_to_mesh!(mesh, back_elements, :Tri3, :BACK)
elements_to_mesh!(mesh, plate_elements, :Tet4, :PLATE)
mesh.element_sets
length(mesh.nodes)
Mesh is ready. Next create problems:
plate = Problem(Elasticity, "plate", 3)
plate_elements = create_elements(mesh, :PLATE)
update!(plate_elements, "youngs modulus", 210e9)
update!(plate_elements, "poissons ratio", 0.3)
add_elements!(plate, plate_elements)
left_elements = create_elements(mesh, :LEFT)
update!(left_elements, "displacement 1", 0.0)
left_bc = Problem(Dirichlet, "left bc", 3, "displacement")
add_elements!(left_bc, left_elements)
right_elements = create_elements(mesh, :RIGHT)
update!(right_elements, "displacement traction force 1", 10e3)
right_bc = Problem(Elasticity, "right bc", 3)
add_elements!(right_bc, right_elements)
down_elements = create_elements(mesh, :DOWN)
update!(down_elements, "displacement 2", 0.0)
down_bc = Problem(Dirichlet, "down bc", 3, "displacement")
add_elements!(down_bc, down_elements)
front_elements = create_elements(mesh, :FRONT)
update!(front_elements, "displacement 3", 0.0)
front_bc = Problem(Dirichlet, "front bc", 3, "displacement")
add_elements!(front_bc, front_elements)
Analysis:
analysis = Analysis(Linear)
add_problems!(analysis, plate, left_bc, right_bc, down_bc, front_bc)
Write results to Xdmf file during analysis
xdmf_output = Xdmf("plate_results"; overwrite=true)
add_results_writer!(analysis, xdmf_output)
run!(analysis)
close(xdmf_output)
Results