Files
JuliaFEM.jl/src/preprocess_abaqus_reader.jl
T

252 lines
8.1 KiB
Julia
Raw Normal View History

2015-06-25 21:17:29 +03:00
# This file is a part of JuliaFEM.
# License is MIT: see https://github.com/JuliaFEM/JuliaFEM.jl/blob/master/LICENSE.md
2016-07-11 04:48:59 +03:00
importall Base
2015-12-01 12:23:51 +02:00
2015-11-29 19:59:47 +02:00
element_has_nodes(::Type{Val{:C3D4}}) = 4
2015-12-01 12:23:51 +02:00
element_has_type( ::Type{Val{:C3D4}}) = :Tet4
2016-07-11 04:48:59 +03:00
element_has_nodes(::Type{Val{:C3D8}}) = 8
element_has_type( ::Type{Val{:C3D8}}) = :Hex8
2015-12-01 12:23:51 +02:00
element_has_nodes(::Type{Val{:C3D10}}) = 10
element_has_type(::Type{Val{:C3D10}}) = :Tet10
2015-11-29 19:59:47 +02:00
element_has_nodes(::Type{Val{:C3D20}}) = 20
2015-12-01 12:23:51 +02:00
2015-11-29 19:59:47 +02:00
element_has_nodes(::Type{Val{:C3D20E}}) = 20
2015-12-01 12:23:51 +02:00
2015-11-29 19:59:47 +02:00
element_has_nodes(::Type{Val{:S3}}) = 3
2015-12-12 15:22:31 +02:00
element_has_type( ::Type{Val{:S3}}) = :Tri3
2015-06-25 20:27:47 +03:00
2015-12-03 16:28:35 +02:00
element_has_nodes(::Type{Val{:STRI65}}) = 6
element_has_type(::Type{Val{:STRI65}}) = :Tri6
2016-07-11 04:48:59 +03:00
element_has_nodes(::Type{Val{:CPS4}}) = 4
element_has_type(::Type{Val{:CPS4}}) = :Quad4
"""
Checks for if line is a comment line or just empty
"""
function empty_or_comment_line{T<:AbstractString}(line::T)
2015-11-29 19:59:47 +02:00
startswith(line, "**") || (length(line) == 0)
2015-06-25 20:27:47 +03:00
end
"""
Function for parsing nodes from the file
"""
2015-12-01 12:23:51 +02:00
function parse_section(model, lines, key::Symbol, idx_start,
idx_end, ::Type{Val{:NODE}})
info("Parsing nodes")
ids = Integer[]
definition = lines[idx_start]
for line in lines[idx_start + 1: idx_end]
if !(empty_or_comment_line(line))
2016-11-17 19:43:20 +02:00
m = matchall(r"[-0-9.eE+]+", line)
node_id = parse(Int, m[1])
coords = float(m[2:end])
2015-12-01 12:23:51 +02:00
model["nodes"][node_id] = coords
end
end
has_set_def = match(r"NSET=([\w\_\-]+)", definition)
if has_set_def != nothing
set_name = has_set_def[1]
2015-12-04 08:27:59 +02:00
info("Creating nset $set_name")
2015-12-01 12:23:51 +02:00
model["nsets"][set_name] = ids
end
end
2015-06-25 20:27:47 +03:00
"""
Custon regex to find match from string. Index used if there are multiple matches
"""
function regex_match(regex_str, line, idx)
return match(regex_str, line).captures[idx]
2015-12-01 12:23:51 +02:00
println(eltype_sym)
end
"""
Simple iterator for comsuming element list. Depending
on the used element, connectivity nodes might be listed
in multiple lines, which is why iterator is used to handle
this problem.
"""
function consumeList(arr, start, stop)
function _it()
for i=start:stop
produce(arr[i])
end
end
Task(_it)
end
"""
Parse elements from input.
"""
2015-12-01 12:23:51 +02:00
function parse_section(model, lines, key, idx_start, idx_end, ::Type{Val{:ELEMENT}})
#definition = uppercase(lines[idx_start])
definition = lines[idx_start]
element_type = regex_match(r"TYPE=([\w\-\_]+)", definition, 1)
eltype_sym = Symbol(element_type)
2015-11-29 19:59:47 +02:00
eltype_nodes = element_has_nodes(Val{eltype_sym})
element_type = element_has_type(Val{eltype_sym})
2015-11-29 14:38:04 +02:00
info("Parsing elements. Type: $(element_type)")
list_iterator = consumeList(lines, idx_start+1, idx_end)
ids = Integer[]
line = consume(list_iterator)
while line != nothing
arr_num_as_str = matchall(r"[0-9]+", line)
numbers = map(x-> parse(Int, x), arr_num_as_str)
if !(empty_or_comment_line(line))
id = numbers[1]
2015-12-01 12:23:51 +02:00
push!(ids, id)
connectivity = numbers[2:end]
2015-11-29 19:59:47 +02:00
while length(connectivity) != eltype_nodes
@assert length(connectivity) < eltype_nodes
line = consume(list_iterator)
arr_num_as_str = matchall(r"[0-9]+", line)
numbers = map(x-> parse(Int, x), arr_num_as_str)
2015-12-01 12:23:51 +02:00
push!(connectivity, numbers...)
end
2015-12-01 12:23:51 +02:00
model["elements"][id] = Dict(("type"=>element_type),
("connectivity"=>connectivity))
end
line = consume(list_iterator)
end
has_set_def = match(r"ELSET=([\w\_\-]+)", definition)
if has_set_def != nothing
set_name = has_set_def[1]
2015-12-04 08:27:59 +02:00
info("Creating elset $set_name")
2015-12-01 12:23:51 +02:00
model["elsets"][set_name] = ids
end
end
"""
Parsing Node- and ElementSets.
"""
2015-11-29 19:59:47 +02:00
function parse_section(model, lines, key, idx_start, idx_end, ::Union{Type{Val{:NSET}}, Type{Val{:ELSET}}})
set_regex_string = Dict(:NSET => r"NSET=([\w\-\_]+)",
:ELSET => r"ELSET=([\w\-\_]+)" )
#definition = uppercase(lines[idx_start])
# FIXME: do not uppercase set names
definition = lines[idx_start]
regex_string = set_regex_string[key]
set_name = regex_match(regex_string, definition, 1)
2015-11-29 14:38:04 +02:00
info("Creating $(lowercase(string(key))) $set_name")
data = Integer[]
if endswith(strip(definition), "GENERATE")
line = lines[idx_start + 1]
m = matchall(r"[0-9]+", line)
first_id, last_id, step = map(x-> parse(Int, x), m)
set_ids = collect(first_id:step:last_id)
2015-12-01 12:23:51 +02:00
push!(data, set_ids...)
else
for line in lines[idx_start + 1: idx_end]
if !(empty_or_comment_line(line))
m = matchall(r"[0-9]+", line)
set_ids = map(s -> parse(Int, s), m)
2015-12-01 12:23:51 +02:00
push!(data, set_ids...)
end
end
end
2015-12-01 12:23:51 +02:00
selected_set = key == :NSET ? "nsets" : "elsets"
model[selected_set][set_name] = data
end
"""
Parse SURFACE keyword
2015-12-01 12:23:51 +02:00
"""
function parse_section(model, lines, key, idx_start, idx_end, ::Type{Val{:SURFACE}})
2015-12-01 12:23:51 +02:00
info("Parsing surface")
#definition = uppercase(lines[idx_start])
definition = lines[idx_start]
#has_set_def = match(r"TYPE=([\w\_\-]+),.*NAME=([\w\_\-]+)", definition)
has_set_def = Dict(map(y -> lowercase(strip(y[1])) => strip(y[2]), map(x -> split(x, "="), matchall(r"([\w\_\-]+[ ]*=[ ]*[\w\_\-]+)", definition))))
has_set_def != nothing || return
info(has_set_def)
set_type = Symbol(has_set_def["type"])
set_name = Symbol(has_set_def["name"])
data = Vector{Tuple{Int64, Symbol}}()
2015-12-01 12:23:51 +02:00
for line in lines[idx_start + 1: idx_end]
empty_or_comment_line(line) && continue
2016-10-12 01:05:06 +03:00
m = match(r"(?P<element_id>\d+),.*(?P<element_side>S\d+).*", line)
if isa(m, Void)
warn("read_abaqus, parsing surface: line $line")
continue
end
element_id = parse(Int, m[:element_id])
element_side = Symbol(m[:element_side])
push!(data, (element_id, element_side))
2015-12-01 12:23:51 +02:00
end
model["surface_types"][set_name] = set_type
model["surfaces"][set_name] = data
return
2015-12-01 12:23:51 +02:00
end
2015-06-25 20:27:47 +03:00
2015-11-28 13:02:56 +02:00
"""
Find lines, which contain keywords, for example "*NODE"
"""
function find_keywords(lines)
indexes = Integer[]
for (idx, line) in enumerate(lines)
if startswith(line, "*") && !startswith(line, "**")
push!(indexes, idx)
2015-06-25 20:27:47 +03:00
end
end
2015-12-01 12:23:51 +02:00
push!(indexes, length(lines) + 1)
return indexes
2015-11-28 13:02:56 +02:00
end
2015-06-25 20:27:47 +03:00
"""
Main function for parsing Abaqus input file.
"""
2015-11-28 13:02:56 +02:00
function parse_abaqus(fid::IOStream)
lines = readlines(fid)
keyword_indexes = find_keywords(lines)
idx_start = keyword_indexes[1]
keyword_sym::Symbol = :none
parser::Function = x->()
2015-12-01 12:23:51 +02:00
model = Dict{AbstractString, Any}()
2015-12-03 15:39:43 +02:00
model["nodes"] = Dict{Int64, Vector{Float64}}()
model["nsets"] = Dict{AbstractString, Vector{Int64}}()
model["elsets"] = Dict{AbstractString, Vector{Int64}}()
2015-12-01 12:23:51 +02:00
model["elements"] = Dict{Integer, Any}()
model["surfaces"] = Dict{Symbol, Vector{Tuple{Int64, Symbol}}}()
model["surface_types"] = Dict{Symbol, Symbol}()
2015-11-28 13:02:56 +02:00
for idx_end in keyword_indexes[2:end]
keyword_line = uppercase(lines[idx_start])
keyword = regex_match(r"\s*([\w ]+)", keyword_line, 1)
k_sym = Symbol(keyword)
args = Tuple{Dict, Vector{Int}, Symbol, Int, Int, Type{Val{k_sym}}}
if method_exists(parse_section, args)
2015-11-29 19:59:47 +02:00
parse_section(model, lines, k_sym, idx_start, idx_end-1, Val{k_sym})
# else
# warn("Unknown section: $(keyword)")
2015-06-25 20:27:47 +03:00
end
2015-11-28 13:02:56 +02:00
idx_start = idx_end
end
return model
2015-06-25 20:27:47 +03:00
end
function abaqus_read_mesh(fn)
model = open(parse_abaqus, fn)
mesh = Mesh()
mesh.nodes = model["nodes"]
for (nset_name, node_ids) in model["nsets"]
mesh.node_sets[Symbol(nset_name)] = Set(node_ids)
end
for (elid, eldata) in model["elements"]
eltype = eldata["type"]
elcon = eldata["connectivity"]
mesh.elements[elid] = elcon
mesh.element_types[elid] = eltype
end
for (elset_name, element_ids) in model["elsets"]
mesh.element_sets[Symbol(elset_name)] = Set(element_ids)
end
2016-11-15 22:01:00 +02:00
mesh.surface_sets = model["surfaces"]
mesh.surface_types = model["surface_types"]
return mesh
end