Files
JuliaFEM.jl/src/preprocess.jl
T

231 lines
7.1 KiB
Julia
Raw Normal View History

# This file is a part of JuliaFEM.
# License is MIT: see https://github.com/JuliaFEM/JuliaFEM.jl/blob/master/LICENSE.md
2016-07-03 05:01:18 +03:00
#=
- read meshes from different formats
- reorder connectivity, create element sets, node sets, ...
- create partitions for parallel runs
- renumber elements / nodes
- maybe precheck for bad elements
- check surface normal direction in boundary elements
- orientation of 2d elements
- etc only topology related stuff
=#
import Base: copy
using JuliaFEM
type Mesh
2017-02-25 18:40:14 +02:00
nodes :: Dict{Int, Vector{Float64}}
node_sets :: Dict{Symbol, Set{Int}}
elements :: Dict{Int, Vector{Int}}
element_types :: Dict{Int, Symbol}
element_codes :: Dict{Int, Symbol}
element_sets :: Dict{Symbol, Set{Int}}
surface_sets :: Dict{Symbol, Vector{Tuple{Int, Symbol}}}
surface_types :: Dict{Symbol, Symbol}
end
function Mesh()
return Mesh(Dict(), Dict(), Dict(), Dict(), Dict(), Dict(), Dict(), Dict())
end
2017-07-21 00:40:52 +03:00
"""
Mesh(m::Dict)
Create new `Mesh` using data `m`. It is assumed that `m` is in format what
`abaqus_read_mesh` in `AbaqusReader.jl` is returning.
"""
function Mesh(m::Dict)
mesh = Mesh()
mesh.nodes = m["nodes"]
mesh.elements = m["elements"]
mesh.element_types = m["element_types"]
mesh.surface_sets = m["surface_sets"]
mesh.surface_types = m["surface_types"]
for (nset_name, node_ids) in m["node_sets"]
mesh.node_sets[Symbol(nset_name)] = Set(node_ids)
end
for (elset_name, element_ids) in m["element_sets"]
mesh.element_sets[Symbol(elset_name)] = Set(element_ids)
end
for (surfset_name, surfaces) in m["surface_sets"]
mesh.surface_sets[Symbol(surfset_name)] = surfaces
end
return mesh
end
function add_node!(mesh::Mesh, nid::Int, ncoords::Vector{Float64})
mesh.nodes[nid] = ncoords
end
2017-02-25 18:40:14 +02:00
function add_nodes!(mesh::Mesh, nodes::Dict{Int, Vector{Float64}})
2016-06-25 04:12:53 +03:00
for (nid, ncoords) in nodes
add_node!(mesh, nid, ncoords)
end
end
function add_node_to_node_set!(mesh::Mesh, set_name, nids...)
2016-06-25 04:12:53 +03:00
if !haskey(mesh.node_sets, set_name)
2017-02-25 18:40:14 +02:00
mesh.node_sets[set_name] = Set{Int}()
2016-06-25 04:12:53 +03:00
end
push!(mesh.node_sets[set_name], nids...)
2017-02-25 18:40:14 +02:00
return
2016-06-25 04:12:53 +03:00
end
2017-02-25 18:40:14 +02:00
""" Create a new node set from nodes in element set. """
2017-02-27 07:33:06 +02:00
function create_node_set_from_element_set!(mesh::Mesh, set_names::String...)
for set_name in set_names
set_name = Symbol(set_name)
info("Creating node set $set_name from element set")
node_ids = Set{Int}()
for elid in mesh.element_sets[set_name]
push!(node_ids, mesh.elements[elid]...)
end
mesh.node_sets[set_name] = node_ids
2017-02-25 18:40:14 +02:00
end
return
end
2017-02-27 08:27:08 +02:00
function create_node_set_from_element_set!(mesh::Mesh, set_name::Symbol)
create_node_set_from_element_set!(mesh, string(set_name))
end
2017-02-25 18:40:14 +02:00
function add_element!(mesh::Mesh, elid::Int, eltype::Symbol, connectivity::Vector{Int})
mesh.elements[elid] = connectivity
mesh.element_types[elid] = eltype
end
2017-02-25 18:40:14 +02:00
function add_elements!(mesh::Mesh, elements::Dict{Int, Tuple{Symbol, Vector{Int}}})
2016-06-25 04:12:53 +03:00
for (elid, (eltype, elcon)) in elements
add_element!(mesh, elid, eltype, elcon)
end
end
function add_element_to_element_set!(mesh::Mesh, set_name, elids...)
if !haskey(mesh.element_sets, set_name)
2017-02-25 18:40:14 +02:00
mesh.element_sets[set_name] = Set{Int}()
end
push!(mesh.element_sets[set_name], elids...)
end
function copy(mesh::Mesh)
mesh2 = Mesh()
mesh2.nodes = copy(mesh.nodes)
mesh2.node_sets = copy(mesh.node_sets)
mesh2.elements = copy(mesh.elements)
mesh2.element_types = copy(mesh.element_types)
mesh2.element_sets = copy(mesh.element_sets)
return mesh2
end
2017-02-25 18:40:14 +02:00
function filter_by_element_id(mesh::Mesh, element_ids::Vector{Int})
mesh2 = copy(mesh)
mesh2.elements = Dict()
for elid in element_ids
if haskey(mesh.elements, elid)
mesh2.elements[elid] = mesh.elements[elid]
end
end
return mesh2
end
function filter_by_element_set(mesh::Mesh, set_name)
filter_by_element_id(mesh::Mesh, collect(mesh.element_sets[set_name]))
end
2016-07-14 12:43:41 +03:00
function create_element(mesh::Mesh, id::Int)
connectivity = mesh.elements[id]
2016-11-13 13:24:08 +02:00
element_type = getfield(JuliaFEM, mesh.element_types[id])
2016-07-14 12:43:41 +03:00
element = Element(element_type, connectivity)
element.id = id
2016-11-28 10:09:48 +02:00
update!(element, "geometry", mesh.nodes)
2016-07-14 12:43:41 +03:00
return element
end
function create_elements(mesh::Mesh; element_type=nothing)
element_ids = collect(keys(mesh.elements))
if element_type != nothing
filter!(id -> mesh.element_types[id] == element_type, element_ids)
end
2016-07-14 12:43:41 +03:00
elements = [create_element(mesh, id) for id in element_ids]
return elements
end
function create_elements(mesh::Mesh, element_sets::Symbol...; element_type=nothing)
if isempty(element_sets)
element_ids = collect(keys(mesh.elements))
else
2017-02-25 18:40:14 +02:00
element_ids = Set{Int}()
for set_name in element_sets
element_ids = union(element_ids, mesh.element_sets[set_name])
end
2016-07-03 05:01:18 +03:00
end
if element_type != nothing
filter!(id -> mesh.element_types[id] == element_type, element_ids)
2016-07-03 05:01:18 +03:00
end
2016-07-14 12:43:41 +03:00
elements = [create_element(mesh, id) for id in element_ids]
2016-07-03 05:01:18 +03:00
return elements
end
function create_elements(mesh::Mesh, element_sets::AbstractString...; element_type=nothing)
element_sets = map(parse, element_sets)
return create_elements(mesh, element_sets...; element_type=element_type)
end
""" find npts nearest nodes from mesh and return id numbers as list. """
2017-02-27 07:33:06 +02:00
function find_nearest_nodes(mesh::Mesh, coords::Vector{Float64}, npts::Int=1; node_set=nothing)
2017-02-25 18:40:14 +02:00
dist = Dict{Int, Float64}()
2016-06-25 04:12:53 +03:00
for (nid, c) in mesh.nodes
2017-02-27 07:33:06 +02:00
if node_set != nothing && !(nid in mesh.node_sets[Symbol(node_set)])
continue
end
2016-06-25 04:12:53 +03:00
dist[nid] = norm(coords-c)
end
s = sort(collect(dist), by=x->x[2])
nd = s[1:npts] # [(id1, dist1), (id2, dist2), ..., (id_npts, dist_npts)]
node_ids = [n[1] for n in nd]
return node_ids
end
2017-02-27 08:27:08 +02:00
function find_nearest_node(mesh::Mesh, coords::Vector{Float64}; node_set=nothing)
return first(find_nearest_nodes(mesh, coords, 1; node_set=node_set))
end
2016-07-03 05:01:18 +03:00
"""
Apply new node ordering to elements. In JuliaFEM same node ordering is used
than in ABAQUS and if mesh is parsed from FEM format with other node ordering
this can be used to reorder nodes.
Parameters
----------
mapping :: Dict{Symbol, Vector{Int}}
e.g. :Tet10, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
"""
function reorder_element_connectivity!(mesh::Mesh, mapping::Dict{Symbol, Vector{Int}})
for (elid, eltype) in mesh.element_types
haskey(mapping, eltype) || continue
new_order = mapping[eltype]
element_connectivity = mesh.elements[elid]
new_element_connectivity = element_connectivity[new_order]
mesh.elements[elid] = new_element_connectivity
end
end
2017-02-25 18:40:14 +02:00
function JuliaFEM.Problem{P<:FieldProblem}(mesh::Mesh, ::Type{P}, name::AbstractString, dimension::Int)
2016-10-01 13:37:15 +03:00
problem = Problem(P, name, dimension)
problem.elements = create_elements(mesh, name)
return problem
end
function JuliaFEM.Problem{P<:BoundaryProblem}(mesh::Mesh, ::Type{P}, name, dimension, parent_field_name)
2016-10-01 13:37:15 +03:00
problem = Problem(P, name, dimension, parent_field_name)
problem.elements = create_elements(mesh, name)
return problem
end