diff --git a/.travis.yml b/.travis.yml index 18ff844..01cbe24 100644 --- a/.travis.yml +++ b/.travis.yml @@ -18,6 +18,7 @@ before_script: - julia --color=yes -e 'Pkg.add("Lint")' - julia --color=yes -e 'Pkg.clone("https://github.com/ahojukka5/CheckHeader.jl.git")' - julia --color=yes -e 'Pkg.clone("https://github.com/ahojukka5/CheckTabs.jl.git")' + - julia --color=yes -e 'Pkg.clone("https://github.com/JuliaFEM/AbaqusReader.jl.git")' script: - julia --color=yes -e 'Pkg.build("JuliaFEM")' - julia --color=yes -e 'using CheckHeader; checkheader("JuliaFEM")' diff --git a/docs/src/index.md b/docs/src/index.md index 37cd556..298dda1 100644 --- a/docs/src/index.md +++ b/docs/src/index.md @@ -6,6 +6,7 @@ ```@meta DocTestSetup = quote using JuliaFEM + using JuliaFEM.Preprocess end ``` @@ -15,7 +16,9 @@ Add here. ## Functions -Add here. +```@docs +JuliaFEM.Preprocess.create_surface_elements +``` ## Index diff --git a/src/JuliaFEM.jl b/src/JuliaFEM.jl index 4d908c7..73eedd5 100644 --- a/src/JuliaFEM.jl +++ b/src/JuliaFEM.jl @@ -137,15 +137,14 @@ export create_elements, Mesh, add_node!, add_nodes!, add_element!, add_elements!, add_element_to_element_set!, add_node_to_node_set!, find_nearest_nodes, find_nearest_node, reorder_element_connectivity!, create_node_set_from_element_set! -include("preprocess_abaqus_reader.jl") -export parse_abaqus, parse_section, parse_element_section, - abaqus_read_mesh, abaqus_read_model + include("preprocess_aster_reader.jl") export aster_create_elements, parse_aster_med_file, is_aster_mail_keyword, parse_aster_header, aster_parse_nodes, aster_renumber_nodes!, aster_renumber_elements!, aster_combine_meshes, aster_read_mesh, filter_by_element_set, filter_by_element_id, MEDFile, aster_read_data, aster_read_mesh_names, aster_read_node_sets, aster_read_nodes, RMEDFile + end module Postprocess @@ -155,10 +154,4 @@ export calc_nodal_values!, get_nodal_vector, get_nodal_dict, copy_field!, calculate_second_moment_of_mass, extract end -module Abaqus -include("abaqus.jl") -export abaqus_read_model, abaqus_run_model, abaqus_open_results, create_surface_elements end - -end - diff --git a/src/abaqus.jl b/src/abaqus.jl deleted file mode 100644 index d3dcf74..0000000 --- a/src/abaqus.jl +++ /dev/null @@ -1,765 +0,0 @@ -# This file is a part of JuliaFEM. -# License is MIT: see https://github.com/JuliaFEM/JuliaFEM.jl/blob/master/LICENSE.md - -import Base: getindex, length - -using JuliaFEM -using JuliaFEM.Preprocess -using JuliaFEM.Postprocess - -### Model definitions for ABAQUS data model - -abstract type AbstractMaterial end -abstract type AbstractMaterialProperty end -abstract type AbstractProperty end -abstract type AbstractStep end -abstract type AbstractBoundaryCondition end -abstract type AbstractOutputRequest end - -type Model - path :: AbstractString - name :: AbstractString - mesh :: Mesh - materials :: Dict{Symbol, AbstractMaterial} - properties :: Vector{AbstractProperty} - boundary_conditions :: Vector{AbstractBoundaryCondition} - steps :: Vector{AbstractStep} - problems :: Vector{Problem} -end - -type SolidSection <: AbstractProperty - element_set :: Symbol - material_name :: Symbol -end - -type Material <: AbstractMaterial - name :: Symbol - properties :: Vector{AbstractMaterialProperty} -end - -type Elastic <: AbstractMaterialProperty - E :: Float64 - nu :: Float64 -end - -type Step <: AbstractStep - kind :: Nullable{Symbol} # STATIC, ... - boundary_conditions :: Vector{AbstractBoundaryCondition} - output_requests :: Vector{AbstractOutputRequest} -end - -type BoundaryCondition <: AbstractBoundaryCondition - kind :: Symbol # BOUNDARY, CLOAD, DLOAD, DSLOAD, ... - data :: Vector - options :: Dict -end - -type OutputRequest <: AbstractOutputRequest - kind :: Symbol # NODE, EL, SECTION, ... - data :: Vector - options :: Dict - target :: Symbol # PRINT, FILE -end - -### Utility functions to parse ABAQUS .inp file to data model - -type Keyword - name :: AbstractString - options :: Vector{Union{AbstractString, Pair}} -end - -function getindex(kw::Keyword, s) - return parse(Dict(kw.options)[s]) -end - -type AbaqusReaderState - section :: Nullable{Keyword} - material :: Nullable{AbstractMaterial} - property :: Nullable{AbstractProperty} - step :: Nullable{AbstractStep} - data :: Vector{AbstractString} -end - -function get_data(state::AbaqusReaderState) - data = [] - for row in state.data - row = strip(row, [' ', ',']) - col = split(row, ',') - col = map(parse, col) - push!(data, col) - end - return data -end - -function get_options(state::AbaqusReaderState) - return Dict(get(state.section).options) -end - -function get_option(state::AbaqusReaderState, what::AbstractString) - return get_options(state)[what] -end - -function length(state::AbaqusReaderState) - return length(state.data) -end - -function is_comment(line) - return startswith(line, "**") -end - -function is_keyword(line) - return startswith(line, "*") && !is_comment(line) -end - -function parse_keyword(line; uppercase_keyword=true) - args = split(line, ",") - args = map(strip, args) - keyword_name = strip(args[1], '*') - if uppercase_keyword - keyword_name = uppercase(keyword_name) - end - keyword = Keyword(keyword_name, []) - for option in args[2:end] - pair = split(option, "=") - if uppercase_keyword - pair[1] = uppercase(pair[1]) - end - if length(pair) == 1 - push!(keyword.options, pair[1]) - elseif length(pair) == 2 - push!(keyword.options, pair[1] => pair[2]) - else - error("Keyword failure: $line, $option, $pair") - end - end - return keyword -end - -macro register_abaqus_keyword(keyword) - underscored = Symbol(replace(keyword, " ", "_")) - quote - global is_abaqus_keyword_registered - typealias $underscored Type{Val{Symbol($keyword)}} - is_abaqus_keyword_registered(::Type{Val{Symbol($keyword)}}) = true - end -end - -function is_abaqus_keyword_registered(s::AbstractString) - return is_abaqus_keyword_registered(Val{Symbol(s)}) -end - -function is_abaqus_keyword_registered(others) - return false -end - -function is_new_section(line) - is_keyword(line) || return false - section = parse_keyword(line) - is_abaqus_keyword_registered(section.name) || return false - return true -end - -function maybe_close_section!(model, state; verbose=true) - isnull(state.section) && return - section_name = get(state.section).name - verbose && info("Close section: $section_name") - args = Tuple{Model, AbaqusReaderState, Type{Val{Symbol(section_name)}}} - if method_exists(close_section!, args) - close_section!(model, state, Val{Symbol(section_name)}) - else - verbose && warn("no close_section! found for $section_name") - end - state.section = nothing -end - -function maybe_open_section!(model, state; verbose=true) - section_name = get(state.section).name - section_options = get(state.section).options - verbose && info("New section: $section_name with options $section_options") - args = Tuple{Model, AbaqusReaderState, Type{Val{Symbol(section_name)}}} - if method_exists(open_section!, args) - open_section!(model, state, Val{Symbol(section_name)}) - else - verbose && warn("no open_section! found for $section_name") - end -end - -function new_section!(model, state, line::AbstractString; verbose=true) - maybe_close_section!(model, state; verbose=verbose) - state.data = [] - state.section = parse_keyword(line) - maybe_open_section!(model, state; verbose=verbose) -end - -# open_section! is called right after keyword is found -function open_section! end - -# close_section! is called at the end or section or before new keyword -function close_section! end - -function process_line!(model, state, line; verbose=false) - if isnull(state.section) - verbose && info("section = nothing! line = $line") - return - end - if is_keyword(line) - warn("missing keyword? line = $line") - # close section, this is probably keyword and collecting data should stop. - maybe_close_section!(model, state) - return - end - push!(state.data, line) -end - -function abaqus_read_model(fn; read_mesh=true) - - model_path = dirname(fn) - model_name = first(splitext(basename(fn))) - model = Model(model_path, model_name, Mesh(), Dict(), [], [], [], []) - - if read_mesh - model.mesh = abaqus_read_mesh(fn) - end - - state = AbaqusReaderState(nothing, nothing, nothing, nothing, []) - - fid = open(fn) - for line in eachline(fid) - line = strip(line) - is_comment(line) && continue - if is_new_section(line) - new_section!(model, state, line) - else - process_line!(model, state, line) - end - end - close(fid) - maybe_close_section!(model, state) - - return model -end - -### Code to parse ABAQUS .inp to data model - -# add here only keywords when planning to define open_section! and/or -# close_section!, i.e. actually parse keyword to model. little bit of -# magic is happening here, but after calling macro there is typealias -# defined i.e. typealias SOLID_SECTION Type{Val{Symbol("SOLID_SECTION")}} -# and also is_keyword_registered("SOLID SECTION") returns true after -# registration, also notice underscoring - -@register_abaqus_keyword("SOLID SECTION") - -@register_abaqus_keyword("MATERIAL") -@register_abaqus_keyword("ELASTIC") - -@register_abaqus_keyword("STEP") -@register_abaqus_keyword("STATIC") -@register_abaqus_keyword("END STEP") - -@register_abaqus_keyword("BOUNDARY") -@register_abaqus_keyword("CLOAD") -@register_abaqus_keyword("DLOAD") -@register_abaqus_keyword("DSLOAD") -const BOUNDARY_CONDITIONS = Union{BOUNDARY,CLOAD,DLOAD,DSLOAD} - -@register_abaqus_keyword("NODE PRINT") -@register_abaqus_keyword("EL PRINT") -@register_abaqus_keyword("SECTION PRINT") -const OUTPUT_REQUESTS = Union{NODE_PRINT,EL_PRINT,SECTION_PRINT} - -## Properties - -function open_section!(model, state, ::SOLID_SECTION) - element_set = get_option(state, "ELSET") - material_name = get_option(state, "MATERIAL") - property = SolidSection(element_set, material_name) - state.property = property - push!(model.properties, property) -end - -function close_section!(model, state, ::SOLID_SECTION) - state.property = nothing -end - -## Materials - -function open_section!(model, state, ::MATERIAL) - material_name = Symbol(get_option(state, "NAME")) - material = Material(material_name, []) - state.material = material - if haskey(model.materials, material_name) - warn("Material $material_name already exists in model, skipping definition.") - else - model.materials[material_name] = material - end -end - -function close_section!(model, state, ::ELASTIC) - # FIXME - @assert length(state) == 1 - E, nu = first(get_data(state)) - material_property = Elastic(E, nu) - material = get(state.material) - push!(material.properties, material_property) -end - -## Steps - -function open_section!(model, state, ::STEP) - step = Step(nothing, Vector(), Vector()) - state.step = step - push!(model.steps, step) -end - -function open_section!(model, state, ::STATIC) - isnull(state.step) && error("*STATIC outside *STEP ?") - get(state.step).kind = :STATIC -end - -function open_section!(model, state, ::END_STEP) - state.step = nothing -end - -## Steps -- boundary conditions - -function close_section!(model, state, ::BOUNDARY_CONDITIONS) - kind = Symbol(get(state.section).name) - data = get_data(state) - options = get_options(state) - bc = BoundaryCondition(kind, data, options) - if isnull(state.step) - push!(model.boundary_conditions, bc) - else - step = get(state.step) - push!(step.boundary_conditions, bc) - end -end - -## Steps -- output requests - -function close_section!(model, state, ::OUTPUT_REQUESTS) - kind, target = map(parse, split(get(state.section).name, " ")) - data = get_data(state) - options = get_options(state) - request = OutputRequest(kind, data, options, target) - step = get(state.step) - push!(step.output_requests, request) -end - - -### Code to use JuliaFEM to run ABAQUS data model - -function determine_problem_type(model::Model) - # FIXME - return Elasticity -end - -function determine_problem_dimension(model::Model) - # FIXME - return 3 -end - -function get_element_section(model::Model, element_set_name::Symbol) - sections = filter(s -> s.element_set == element_set_name, model.properties) - length(sections) == 1 || error("Multiple sections found for element set $element_set_name") - return sections[1] -end - -function get_material(model::Model, material_name) - return model.materials[material_name] -end - -function create_problem(model::Model, element_set_name::Symbol; verbose=true) - problem_type = determine_problem_type(model) - problem_name = "$problem_type $element_set_name" - problem_dimension = determine_problem_dimension(model) - problem = Problem(problem_type, problem_name, problem_dimension) - problem.elements = create_elements(model.mesh, element_set_name) - section = get_element_section(model, element_set_name) - material = get_material(model, section.material_name) - for mp in material.properties - if isa(mp, Elastic) - verbose && info("$element_set_name: elastic material, E = $(mp.E), nu = $(mp.nu)") - update!(problem.elements, "youngs modulus", mp.E) - update!(problem.elements, "poissons ratio", mp.nu) - end - end - return problem -end - -""" Dirichlet boundary condition. """ -function create_boundary_problem(model::Model, bc::AbstractBoundaryCondition, ::BOUNDARY; verbose=true) - dim = determine_problem_dimension(model) - problem = Problem(Dirichlet, "Dirichlet boundary *BOUNDARY", dim, "displacement") - for row in bc.data - - if isa(row[1], AbstractString) # node set given - nodes = model.mesh.node_sets[bc_name] - else # single node given - nodes = [row[1]] - end - - elements = [Element(Poi1, [id]) for id in nodes] - update!(elements, "geometry", model.mesh.nodes) - - for dof in row[2]:row[end] - # FIXME - val = 0.0 - update!(elements, "displacement $dof", val) - verbose && info("Nodes ", join(nodes, ", "), " dof $dof => $val") - end - - push!(problem, elements) - end - return problem -end - -""" Distributed surface load (DSLOAD). """ -function create_boundary_problem(model::Model, bc::AbstractBoundaryCondition, ::DSLOAD; verbose=false) - dim = determine_problem_dimension(model) - problem = Problem(Elasticity, "Distributed surface load *DSLOAD", dim) - for row in bc.data - bc_name, bc_type, pressure = row - bc_type == :P || error("bc_type = $bc_type != :P") - elements = [] - for (parent_element_id, parent_element_side) in model.mesh.surface_sets[bc_name] - parent_element_type = model.mesh.element_types[parent_element_id] - parent_element_connectivity = model.mesh.elements[parent_element_id] - - child_element_type, child_element_lconn, child_element_connectivity = - get_child_element(parent_element_type, parent_element_side, - parent_element_connectivity) - - verbose && info("parent element : $parent_element_id, $parent_element_type, $parent_element_connectivity, $parent_element_side") - verbose && info("child element : $child_element_type, $child_element_connectivity") - - child_element = Element(JuliaFEM.(child_element_type), child_element_connectivity) - push!(elements, child_element) - end - update!(elements, "geometry", model.mesh.nodes) - update!(elements, "surface pressure", pressure) - push!(problem, elements) - end - return problem -end - -""" Distributed load (DLOAD). """ -function create_boundary_problem(model::Model, bc::AbstractBoundaryCondition, ::DLOAD; verbose=false) - dim = determine_problem_dimension(model) - problem = Problem(Elasticity, "Distributed load *DLOAD", dim) - for row in bc.data - parent_element_id, parent_element_side, pressure = row - parent_element_type = model.mesh.element_types[parent_element_id] - parent_element_connectivity = model.mesh.elements[parent_element_id] - - child_element_type, child_element_lconn, child_element_connectivity = - get_child_element(parent_element_type, parent_element_side, - parent_element_connectivity) - - verbose && info("parent element : $parent_element_id, $parent_element_type, $parent_element_connectivity, $parent_element_side") - verbose && info("child element : $child_element_type, $child_element_connectivity") - - child_element = Element(getfield(JuliaFEM, child_element_type), child_element_connectivity) - update!(child_element, "geometry", model.mesh.nodes) - update!(child_element, "surface pressure", -pressure) - push!(problem.elements, child_element) - end - return problem -end - -""" Concentrated load (CLOAD). """ -function create_boundary_problem(model::Model, bc::AbstractBoundaryCondition, ::CLOAD; verbose=false) - dim = determine_problem_dimension(model) - problem = Problem(Elasticity, "Concentrated load *CLOAD", dim) - nodes = sort(unique([row[1] for row in bc.data])) - elements = Dict() - for node in nodes - element = Element(Poi1, [node]) - update!(element, "geometry", model.mesh.nodes) - elements[node] = element - end - for row in bc.data - node, dof, load = row - update!(elements[node], "concentrated force $dof", load) - end - problem.elements = collect(values(elements)) - return problem -end - -function create_boundary_problem(model::Model, bc::AbstractBoundaryCondition) - create_boundary_problem(model, bc, Val{bc.kind}) -end - -""" Given element code, element side and global connectivity, determine boundary -element. E.g. for Tet4 we have 4 sides S1..S4 and boundary element is of type Tri3. -""" -function get_child_element(element_type::Symbol, element_side::Symbol, - element_connectivity::Vector{Int64}) - - element_mapping = Dict( - :Tet4 => Dict( - :S1 => (:Tri3, [1, 3, 2]), - :S2 => (:Tri3, [1, 2, 4]), - :S3 => (:Tri3, [2, 3, 4]), - :S4 => (:Tri3, [1, 4, 3])), - :Tet10 => Dict( - :S1 => (:Tri6, [1, 3, 2, 7, 6, 5]), - :S2 => (:Tri6, [1, 2, 4, 5, 9, 8]), - :S3 => (:Tri6, [2, 3, 4, 6, 10, 9]), - :S4 => (:Tri6, [1, 4, 3, 8, 10, 7])), - :Hex8 => Dict( - :P1 => (:Quad4, [1, 2, 3, 4]), - :P2 => (:Quad4, [5, 8, 7, 6]), - :P3 => (:Quad4, [1, 5, 6, 2]), - :P4 => (:Quad4, [2, 6, 7, 3]), - :P5 => (:Quad4, [3, 7, 8, 4]), - :P6 => (:Quad4, [4, 8, 5, 1])) - ) - - if !haskey(element_mapping, element_type) - error("Unable to find child element for element of type $element_type for side $element_side, check mapping.") - end - - if !haskey(element_mapping[element_type], element_side) - error("Unable to find child element side mapping for element of type $element_type for side $element_side, check mapping.") - end - - child_element, child_element_lconn = element_mapping[element_type][element_side] - child_element_gconn = element_connectivity[child_element_lconn] - return child_element, child_element_lconn, child_element_gconn - end - - function determine_solver_type(model::Model, step::AbstractStep) - # FIXME - return Linear - end - - function process_output_request(model::Model, solver::Solver, output_request::AbstractOutputRequest) - kind = Val{output_request.kind} - target = Val{output_request.target} - process_output_request(model, solver, output_request, kind, target) -end - -function process_output_request(model::Model, solver::Solver, output_request::AbstractOutputRequest, - ::Type{Val{:NODE}}, ::Type{Val{:PRINT}}) - data = output_request.data - options = output_request.options - code_mapping = Dict( - :COORD => "geometry", - :U => "displacement", - :CF => "concentrated force", - :RF => "reaction force") - abbr_mapping = Dict(:COORD => :COOR) - for row in data - info(repeat("-", 80)) - codes = join(row, ", ") - info("*NODE PRINT request, with fields $codes") - if length(options) != 0 - info("Additional options: $options") - end - info(repeat("-", 80)) - tables = Any[] - for code in row - haskey(code_mapping, code) || continue - field_name = code_mapping[code] - abbr = get(abbr_mapping, code, code) - #table = solver(DataFrame, field_name, abbr, solver.time) - #push!(tables, table) - end - length(tables) != 0 || continue - results = join(tables..., on=:NODE, kind=:outer) - sort!(results, cols=[:NODE]) - println() - println(results) - println() - end -end - -function process_output_request(model::Model, solver::Solver, output_request::AbstractOutputRequest, - ::Type{Val{:EL}}, ::Type{Val{:PRINT}}) - data = output_request.data - options = output_request.options - code_mapping = Dict( - :COORD => "geometry", - :S => "stress", - :E => "strain") - abbr_mapping = Dict(:COORD => :COOR) - for row in data - info(repeat("-", 80)) - codes = join(row, ", ") - info("*EL PRINT request, with fields $codes") - if length(options) != 0 - info("Additional options: $options") - end - info(repeat("-", 80)) - #= to be fixed - tables = Any[] - for code in row - haskey(code_mapping, code) || continue - field_name = code_mapping[code] - abbr = get(abbr_mapping, code, code) - table = solver(DataFrame, solver.time, Val{code}) - push!(tables, table) - end - length(tables) != 0 || continue - results = first(tables) - if length(tables) > 1 - for i=2:length(tables) - results = join(results, tables[i], on=:ELEMENT, kind=:outer) - end - end - #sort!(results; cols=[:ELEMENT, :IP]) - # filter out elements with id -1, they are automatically created boundary elements - fel = find(results[:ELEMENT] .!= Symbol("E-1")) - results = results[fel, :] - println() - println(results) - println() - =# - end -end - -function process_output_request(model::Model, solver::Solver, output_request::AbstractOutputRequest, - ::Type{Val{:SECTION}}, ::Type{Val{:PRINT}}) - data = output_request.data - options = output_request.options - info("SECTION PRINT output request, with data $data and options $options") -end - -function (model::Model)() - info("Starting JuliaFEM-ABAQUS solver.") - - # 1. create field problems and add elements - element_sets = collect(keys(model.mesh.element_sets)) - info("Creating problems for element sets ", join(element_sets, ", ")) - model.problems = [create_problem(model, elset) for elset in element_sets] - - # 2. create boundary problems (the ones defined before *STEP) - info("Boundary conditions defined before *STEP") - for (i, bc) in enumerate(model.boundary_conditions) - info("$i $(bc.kind)") - end - boundary_problems = [create_boundary_problem(model, bc) for bc in model.boundary_conditions] - - # 3. loop steps - for step in model.steps - # 3.1 add boundary conditions defined inside *STEP - step_problems = [create_boundary_problem(model, bc) for bc in step.boundary_conditions] - # 3.2 create solver and solve set of problems - solver_type = determine_solver_type(model, step) - solver_description = "$solver_type solver" - solver = Solver(solver_type, solver_description) - all_problems = [model.problems; boundary_problems; step_problems] - push!(solver, all_problems...) - solver() - info(repeat("-", 80)) - info("Simulation ready, processing output requests") - info(repeat("-", 80)) - # 3.3 postprocessing based on output requests - for output_request in step.output_requests - process_output_request(model, solver, output_request) - end - end - - return 0 -end - -function abaqus_download(name) - fn = "$name.inp" - if !haskey(ENV, "ABAQUS_DOWNLOAD_URL") - info(""" - ABAQUS input file $fn not found and ABAQUS_DOWNLOAD_URL not set, unable to - download file. To enable automatic model downloading, set environment variable - ABAQUS_URL to point url to models.""") - return 1 - end - url = ENV["ABAQUS_DOWNLOAD_URL"] - if haskey(ENV, "ABAQUS_DOWNLOAD_DIR") - fn = rstrip(ENV["ABAQUS_DOWNLOAD_DIR"], '/') * "/" * fn - end - if !isfile(fn) - info("Downloading model $name ...") - download("$url/$name.inp", fn) - end - return 0 -end - -""" Return input file name. """ -function abaqus_input_file_name(name) - fn = "$name.inp" - isfile(fn) && return fn - if haskey(ENV, "ABAQUS_DOWNLOAD_DIR") - fn = rstrip(ENV["ABAQUS_DOWNLOAD_DIR"], '/') * "/" * fn - end - isfile(fn) && return fn - return "" -end - -function abaqus_input_file_path(name) - return dirname(abaqus_input_file_name(name)) -end - -function abaqus_open_results(name) - path = abaqus_input_file_path(name) - result_file = "$path/$name.xmf" - return Xdmf(result_file) -end - -### JuliaFEM-ABAQUS interface entry point - -""" -Run ABAQUS model. If input file is not found, attempt to fetch it from internet -if fetch is set to true and ABAQUS_DOWNLOAD_URL is set. Return exit code 0 if -execution of model is success. -""" -function abaqus_run_model(name; fetch=false, verbose=false) - - if !isfile("$name.inp") && fetch - status = abaqus_download(name) - status == 0 || return status # download failed - end - - fn = abaqus_input_file_name(name) - - if verbose - println(repeat("-", 80)) - println("Running ABAQUS model $name from file $fn") - println(repeat("-", 80)) - println(readstring(fn)) - println(repeat("-", 80)) - end - - model = abaqus_read_model(fn) - status = model() - return status -end - - -""" -This function gerates surface elements from solid elements - -slave = create_surface_elements(mesh, :slave_surf) -master = create_surface_elements(mesh, :master_surf) -""" -function create_surface_elements(mesh::Mesh, surface_name::Symbol) - elements = [] - for (parent_element_id, parent_element_side) in mesh.surface_sets[surface_name] - parent_element_type = mesh.element_types[parent_element_id] - parent_element_connectivity = mesh.elements[parent_element_id] - - child_element_type, child_element_lconn, child_element_connectivity = - get_child_element(parent_element_type, parent_element_side, - parent_element_connectivity) - - child_element = Element(getfield(JuliaFEM, child_element_type), child_element_connectivity) - push!(elements, child_element) - end - update!(elements, "geometry", mesh.nodes) - return elements -end - -function create_surface_elements(mesh::Mesh, surface_name::String) - return create_surface_elements(mesh, Symbol(surface_name)) -end - diff --git a/src/preprocess.jl b/src/preprocess.jl index 9e488ff..1c8a552 100644 --- a/src/preprocess.jl +++ b/src/preprocess.jl @@ -31,6 +31,31 @@ function Mesh() return Mesh(Dict(), Dict(), Dict(), Dict(), Dict(), Dict(), Dict(), Dict()) end +""" + 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 @@ -203,3 +228,47 @@ function JuliaFEM.Problem{P<:BoundaryProblem}(mesh::Mesh, ::Type{P}, name, dimen problem.elements = create_elements(mesh, name) return problem end + +using AbaqusReader + +function abaqus_read_mesh(fn::String) + m = AbaqusReader.abaqus_read_mesh(fn) + return Mesh(m) +end + +""" + create_surface_elements(mesh::Mesh, surface_name::Symbol) + +Create a set of surface elements from solid elements. + +Notation follow what is defined in ABAQUS. For example, if solid elements +are Tet10, surface elements will be Tri6 and they can be used to define +boundary conditions. +""" +function create_surface_elements(mesh::Mesh, surface_name::Symbol) + elements = Element[] + for (elid, elsi) in mesh.surface_sets[surface_name] + elty = mesh.element_types[elid] + elco = mesh.elements[elid] + chel, chcon = AbaqusReader.create_surface_element(elty, elsi, elco) + ch = Element(getfield(JuliaFEM, chel), chcon) + push!(elements, ch) + end + update!(elements, "geometry", mesh.nodes) + return elements +end + +""" + create_surface_elements(mesh::Mesh, surface_name::String) + +Create a set of surface elements from solid elements. + +Notation follow what is defined in ABAQUS. For example, if solid elements +are Tet10, surface elements will be Tri6 and they can be used to define +boundary conditions. +""" +function create_surface_elements(mesh::Mesh, surface_name::String) + return create_surface_elements(mesh, Symbol(surface_name)) +end + +export abaqus_read_mesh, create_surface_elements diff --git a/src/preprocess_abaqus_reader.jl b/src/preprocess_abaqus_reader.jl deleted file mode 100644 index 7a0993d..0000000 --- a/src/preprocess_abaqus_reader.jl +++ /dev/null @@ -1,264 +0,0 @@ -# This file is a part of JuliaFEM. -# License is MIT: see https://github.com/JuliaFEM/JuliaFEM.jl/blob/master/LICENSE.md - -element_has_nodes(::Type{Val{:C3D4}}) = 4 -element_has_type( ::Type{Val{:C3D4}}) = :Tet4 - -element_has_nodes(::Type{Val{:C3D8}}) = 8 -element_has_type( ::Type{Val{:C3D8}}) = :Hex8 - -element_has_nodes(::Type{Val{:C3D10}}) = 10 -element_has_type(::Type{Val{:C3D10}}) = :Tet10 - -element_has_nodes(::Type{Val{:C3D20}}) = 20 - -element_has_nodes(::Type{Val{:C3D20E}}) = 20 - -element_has_nodes(::Type{Val{:S3}}) = 3 -element_has_type( ::Type{Val{:S3}}) = :Tri3 - -element_has_nodes(::Type{Val{:STRI65}}) = 6 -element_has_type(::Type{Val{:STRI65}}) = :Tri6 - -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) - startswith(line, "**") || (length(line) == 0) -end - -""" -Function for parsing nodes from the file -""" -function parse_section(model, lines, key::Symbol, idx_start, - idx_end, ::Type{Val{:NODE}}) - - info("Parsing *NODE block between lines $idx_start .. $idx_end") - nnodes = 0 - ids = Integer[] - definition = lines[idx_start] - debug("Definition line = $definition") - for line in lines[idx_start + 1: idx_end] - if !(empty_or_comment_line(line)) - m = matchall(r"[-0-9.eE+]+", line) - node_id = parse(Int, m[1]) - coords = float(m[2:end]) - model["nodes"][node_id] = coords - nnodes += 1 - end - end - info("$nnodes nodes found") - has_set_def = match(r"NSET=([\w\_\-]+)", definition) - if has_set_def != nothing - set_name = has_set_def[1] - info("Creating node set $set_name") - model["nsets"][set_name] = ids - end -end - -""" -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] - 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. -""" -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) - eltype_nodes = element_has_nodes(Val{eltype_sym}) - element_type = element_has_type(Val{eltype_sym}) - 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] - push!(ids, id) - connectivity = numbers[2:end] - 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) - push!(connectivity, numbers...) - end - 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] - info("Creating elset $set_name") - model["elsets"][set_name] = ids - end -end - -""" -Parsing Node- and ElementSets. -""" -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) - 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) - 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) - try - push!(data, set_ids...) - catch err - if isa(err, MethodError) - warn("Problems with element set creation") - end - end - end - end - end - selected_set = key == :NSET ? "nsets" : "elsets" - model[selected_set][set_name] = data -end - -""" -Parse SURFACE keyword -""" -function parse_section(model, lines, key, idx_start, idx_end, ::Type{Val{:SURFACE}}) - debug("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 - debug(has_set_def) - set_type = Symbol(get(has_set_def, "type", "UNKNOWN")) - set_name = Symbol(has_set_def["name"]) - data = Vector{Tuple{Int64, Symbol}}() - for line in lines[idx_start + 1: idx_end] - empty_or_comment_line(line) && continue - m = match(r"(?P\d+),.*(?PS\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)) - end - model["surface_types"][set_name] = set_type - model["surfaces"][set_name] = data - return -end - -""" -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) - end - end - return indexes -end - -""" -Main function for parsing Abaqus input file. -""" -function parse_abaqus(fid::IOStream) - lines = readlines(fid) - keyword_indexes = find_keywords(lines) - nkeyword_indexes = length(keyword_indexes) - debug("$nkeyword_indexes keyword indexes found: $keyword_indexes") - - push!(keyword_indexes, length(lines)+1) - idx_start = keyword_indexes[1] - keyword_sym::Symbol = :none - parser::Function = x->() - model = Dict{AbstractString, Any}() - model["nodes"] = Dict{Int64, Vector{Float64}}() - model["nsets"] = Dict{AbstractString, Vector{Int64}}() - model["elsets"] = Dict{AbstractString, Vector{Int64}}() - model["elements"] = Dict{Integer, Any}() - model["surfaces"] = Dict{Symbol, Vector{Tuple{Int64, Symbol}}}() - model["surface_types"] = Dict{Symbol, Symbol}() - for idx_end in keyword_indexes[2:end] - keyword_line = strip(uppercase(lines[idx_start])) - keyword = strip(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) - parse_section(model, lines, k_sym, idx_start, idx_end-1, Val{k_sym}) - else - debug("Unknown section: '$(keyword)'") - debug("keyword_line = '$keyword_line'") - debug("idx_start = $idx_start, idx_end = $idx_end") - end - idx_start = idx_end - end - return model -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 - mesh.surface_sets = model["surfaces"] - mesh.surface_types = model["surface_types"] - return mesh -end - diff --git a/test/test_abaqus_verification.jl b/test/test_abaqus_verification.jl deleted file mode 100644 index 4c298de..0000000 --- a/test/test_abaqus_verification.jl +++ /dev/null @@ -1,95 +0,0 @@ -# This file is a part of JuliaFEM. -# License is MIT: see https://github.com/JuliaFEM/JuliaFEM.jl/blob/master/LICENSE.md - -using JuliaFEM -using JuliaFEM.Preprocess -using JuliaFEM.Postprocess -using JuliaFEM.Abaqus -using JuliaFEM.Testing -using DataFrames - -# to turn on automatic file download, set -# ENV["ABAQUS_DOWNLOAD_URL"] = "http://:2080/v2016/books/eif" -# if don't want to download all stuff to current directory, set also -# ENV["ABAQUS_DOWNLOAD_DIR"] = "/tmp" - -""" Run test, return true if simulation is succesfull, i.e. no errors raise -during parsing .inp file or execution of model. This doesn't mean that results -are meaningful; they must be checked in separately. Running model only verifies -that no catastrophic failures happen during file parsing. """ -function abaqus_run_test(name) - return_code = abaqus_run_model(name; fetch=true, verbose=true) - return_code == 0 && return true - return false -end - -@testset "JuliaFEM-ABAQUS interface" begin - @testset "1 Element Verification" begin - @testset "1.2 Eigenvalue tests" begin - @testset "1.2.1 Eigenvalue extraction for single unconstrained elements" begin - @testset "Acoustic elements" begin - @testset "AC1D2 elements." begin -# abaqus_run_test("ec12afe1") || return - end - end - @testset "Three-dimensional continuum elements" begin - @testset "C3D10 elements." begin -# abaqus_run_test("ec3asfe1") || return - end - end - end - end - @testset "1.3 Simple load tests" begin - @testset "1.3.1 Membrane loading of plane stress, plane strain, membrane, and shell elements" begin - @testset "CPS4 elements." begin -# abaqus_run_test("ecs4sfs1") || return - end - end - @testset "1.3.3 Three-dimensional solid elements" begin - @testset "C3D8 elements." begin - abaqus_run_test("ec38sfs2") || return - #res = abaqus_open_results("ec38sfs2") - -node_output1 = wsv""" -NODE U1 U2 U3 COOR1 COOR2 COOR3 -1 -2.0000E-33 -2.0000E-33 -2.0000E-33 0.000 0.000 0.000 -2 -2.6667E-05 -1.0000E-33 -1.7333E-04 2.000 0.000 0.000 -3 -2.0000E-04 -2.6667E-05 -1.7333E-04 2.000 2.000 0.000 -4 -1.7333E-04 -2.6667E-05 -1.0000E-33 0.000 2.000 0.000 -5 -3.6777E-48 -8.6667E-05 -1.3333E-05 0.000 0.000 1.000 -6 -2.6667E-05 -8.6667E-05 -1.8667E-04 2.000 0.000 1.000 -7 -2.0000E-04 -1.1333E-04 -1.8667E-04 2.000 2.000 1.000 -8 -1.7333E-04 -1.1333E-04 -1.3333E-05 0.000 2.000 1.000 -""" - -node_output_2 = wsv""" -NODE RF1 RF2 RF3 CF1 CF2 CF3 -1 1500.000 1500.000 1000.000 0.000 0.000 0.000 -2 0.000 500.000 0.000 1500.000 0.000 0.000 -3 0.000 0.000 0.000 500.000 500.000 -1000.000 -4 0.000 0.000 0.000 500.000 1500.000 0.000 -5 -500.000 0.000 0.000 0.000 -500.000 1000.000 -6 0.000 0.000 0.000 -500.000 -1500.000 0.000 -7 0.000 0.000 0.000 -1500.000 -1500.000 -1000.000 -8 0.000 0.000 0.000 -1500.000 -500.000 0.000 -""" - #= to check also results: - side, opts = read_result(xdmf, "SECTION/side") - @test isapprox(side["SOFM"], 3464.0) - @test isapprox(side["SOF1"], 2000.0) - @test isapprox(side["SOF2"], 2000.0) - @test isapprox(side["SOF3"], 2000.0) - @test isapprox(side["SOMM"], 2828.0) - @test isapprox(side["SOM1"], 0.0) - @test isapprox(side["SOM2"], 2000.0) - @test isapprox(side["SOM3"], -2000.0) - @test isapprox(side["SOAREA"], 2.000) - @test isapprox(side["SOCF1"], 2/3) - @test isapprox(side["SOCF2"], 2/3) - @test isapprox(side["SOCF3"], 1/6) - =# - end - end - end - end -end diff --git a/test/test_preprocess_abaqus_reader.jl b/test/test_preprocess_abaqus_reader.jl deleted file mode 100644 index 94a7973..0000000 --- a/test/test_preprocess_abaqus_reader.jl +++ /dev/null @@ -1,110 +0,0 @@ -# This file is a part of JuliaFEM. -# License is MIT: see https://github.com/JuliaFEM/JuliaFEM.jl/blob/master/LICENSE.md - -using JuliaFEM -using JuliaFEM.Preprocess -using JuliaFEM.Abaqus -using JuliaFEM.Testing -using JuliaFEM.Preprocess: element_has_nodes, element_has_type - -@testset "read inp file" begin - model = open(parse_abaqus, joinpath(Pkg.dir("JuliaFEM"),"geometry","3d_beam","palkki.inp")) - @test length(model["nodes"]) == 298 - @test length(model["elements"]) == 120 - @test length(model["elsets"]["Body1"]) == 120 - @test length(model["nsets"]["SUPPORT"]) == 9 - @test length(model["nsets"]["LOAD"]) == 9 - @test length(model["nsets"]["TOP"]) == 83 -end - -@testset "test read element section" begin - data = """*ELEMENT, TYPE=C3D10, ELSET=BEAM - 1, 243, 240, 191, 117, 245, 242, 244, - 1, 2, 196 - 2, 204, 199, 175, 130, 207, 208, 209, - 3, 4, 176 - """ - data = split(data, "\n") - model = Dict{AbstractString, Any}() - model["nsets"] = Dict{AbstractString, Vector{Int}}() - model["elsets"] = Dict{AbstractString, Vector{Int}}() - model["elements"] = Dict{Integer, Any}() - parse_section(model, data, :ELEMENT, 1, 5, Val{:ELEMENT}) - @test length(model["elements"]) == 2 - @test model["elements"][1]["connectivity"] == [243, 240, 191, 117, 245, 242, 244, 1, 2, 196] - @test model["elements"][2]["connectivity"] == [204, 199, 175, 130, 207, 208, 209, 3, 4, 176] - @test model["elsets"]["BEAM"] == [1, 2] -end - -@testset "parse nodes from abaqus .inp file to Mesh" begin - fn = joinpath(Pkg.dir("JuliaFEM"), "test", "testdata","cube_tet4.inp") - mesh = abaqus_read_mesh(fn) - info(mesh.surface_sets) - @test length(mesh.nodes) == 10 - @test length(mesh.elements) == 17 - @test haskey(mesh.elements, 1) - @test mesh.elements[1] == [8, 10, 1, 2] - @test mesh.element_types[1] == :Tet4 - @test haskey(mesh.node_sets, :SYM12) - @test haskey(mesh.element_sets, :CUBE) - @test haskey(mesh.surface_sets, :LOAD) - @test haskey(mesh.surface_sets, :ORDER) - @test length(mesh.surface_sets[:LOAD]) == 2 - @test mesh.surface_sets[:LOAD][1] == (16, :S1) - @test mesh.surface_types[:LOAD] == :ELEMENT - @test length(Set(map(size, values(mesh.nodes)))) == 1 - elements = create_surface_elements(mesh,:LOAD) - @test get_connectivity(elements[1]) == [8,10,9] -end - -@testset "parse nodes from abaqus .inp file to Mesh (NX export)" begin - fn = joinpath(Pkg.dir("JuliaFEM"), "test", "testdata","nx_export_problem.inp") - mesh = abaqus_read_mesh(fn) - @test length(mesh.nodes) == 3 -end - -@testset "parse abaqus .inp created using hypermesh" begin - data = """ -** -** ABAQUS Input Deck Generated by HyperMesh Version : 14.0.120.28 -** Generated using HyperMesh-Abaqus Template Version : 14.0.120 -** -** Template: ABAQUS/STANDARD 3D -** -*NODE , Nset = nset_csys0 - 1, 2.649428 , -21.93735 , 217.2934 - 2, 27.54531 , 1.108443 , 228.8077 -""" - fn = tempname() * ".inp" - open(fn, "w") do fid write(fid, data) end - mesh = abaqus_read_mesh(fn) - @test length(mesh.nodes) == 2 -end - -@testset "Elemement types and nodes" begin - @test element_has_nodes(Val{:C3D4}) == 4 - @test element_has_type(Val{:C3D4}) == :Tet4 - @test element_has_nodes(Val{:C3D8}) == 8 - @test element_has_type(Val{:C3D8}) == :Hex8 - @test element_has_nodes(Val{:C3D10}) == 10 - @test element_has_type(Val{:C3D10}) == :Tet10 - @test element_has_nodes(Val{:C3D20}) == 20 - @test element_has_nodes(Val{:C3D20E}) == 20 - @test element_has_nodes(Val{:S3}) == 3 - @test element_has_type(Val{:S3}) == :Tri3 - @test element_has_nodes(Val{:STRI65}) == 6 - @test element_has_type(Val{:STRI65}) == :Tri6 - @test element_has_nodes(Val{:CPS4}) == 4 - @test element_has_type(Val{:CPS4}) == :Quad4 -end - -@testset "GENERATE keyword" begin - data = """ -*NSET, NSET=testgen, GENERATE -7,13,2 -""" - fn = tempname() * ".inp" - open(fn, "w") do fid write(fid, data) end - mesh = abaqus_read_mesh(fn) - @test mesh.node_sets[:testgen] == Set([7,9,13,11]) -end diff --git a/test/test_problems_contact_3d.jl b/test/test_problems_contact_3d.jl index 3dd3c7b..b1889d9 100644 --- a/test/test_problems_contact_3d.jl +++ b/test/test_problems_contact_3d.jl @@ -5,7 +5,6 @@ using JuliaFEM using JuliaFEM.Preprocess using JuliaFEM.Postprocess using JuliaFEM.Testing -using JuliaFEM.Abaqus: create_surface_elements tet4_meshfile = "test_problems_contact_3d/tet4.inp" tet10_meshfile = "test_problems_contact_3d/tet10.inp" diff --git a/test/test_problems_mortar_3d.jl b/test/test_problems_mortar_3d.jl index db2325a..0060c5a 100644 --- a/test/test_problems_mortar_3d.jl +++ b/test/test_problems_mortar_3d.jl @@ -5,7 +5,6 @@ using JuliaFEM using JuliaFEM.Preprocess using JuliaFEM.Postprocess using JuliaFEM.Testing -using JuliaFEM.Abaqus: create_surface_elements ### temperature patch tests, sl tet4, dl tet4, sl tet10, dl tet 10 diff --git a/test/test_problems_mortar_3d_lowlevel.jl b/test/test_problems_mortar_3d_lowlevel.jl index 81c535a..7321c0d 100644 --- a/test/test_problems_mortar_3d_lowlevel.jl +++ b/test/test_problems_mortar_3d_lowlevel.jl @@ -5,7 +5,6 @@ using JuliaFEM using JuliaFEM.Preprocess using JuliaFEM.Postprocess using JuliaFEM.Testing -using JuliaFEM.Abaqus: create_surface_elements @testset "forget to add elements to problem" begin X = Dict( diff --git a/test/test_solvers_abaqus_model.jl b/test/test_solvers_abaqus_model.jl deleted file mode 100644 index 9b5fc4d..0000000 --- a/test/test_solvers_abaqus_model.jl +++ /dev/null @@ -1,48 +0,0 @@ -# This file is a part of JuliaFEM. -# License is MIT: see https://github.com/JuliaFEM/JuliaFEM.jl/blob/master/LICENSE.md - -using JuliaFEM -using JuliaFEM.Preprocess -using JuliaFEM.Postprocess -using JuliaFEM.Abaqus -using JuliaFEM.Testing - -@testset "parse abaqus inp file to AbaqusModel" begin - fn = Pkg.dir("JuliaFEM") * "/test/testdata/cube_tet4.inp" - model = abaqus_read_model(fn) - - @test length(model.properties) == 1 - section = first(model.properties) - @test section.element_set == :CUBE - @test section.material_name == :MAT - - @test haskey(model.materials, :MAT) - material = model.materials[:MAT] - @test isapprox(first(material.properties).E, 208.0e3) - - @test length(model.steps) == 1 - step = first(model.steps) - @test length(step.boundary_conditions) == 2 - - bc = step.boundary_conditions[1] - @test bc.data[1] == [:SYM12, 3] - @test bc.data[2] == [:SYM23, 1] - @test bc.data[3] == [:SYM13, 2] - - load = step.boundary_conditions[2] - @test load.data[1] == [:LOAD, :P, 1.00000] -end - -#= -@testset "given abaqus model solve field" begin - fn = Pkg.dir("JuliaFEM") * "/test/testdata/cube_tet4.inp" - model = abaqus_read_model(fn) - problems = model() - body = first(problems) - info(body("displacement", 0.0)) - result = XDMF() - xdmf_new_result!(result, body, 0.0) - xdmf_save_field!(result, body, 0.0, "displacement"; field_type="Vector") - xdmf_save!(result, "/tmp/cube_tet4.xmf") -end -=# diff --git a/test/test_solvers_postprocess.jl b/test/test_solvers_postprocess.jl index 8b277f6..cc818fb 100644 --- a/test/test_solvers_postprocess.jl +++ b/test/test_solvers_postprocess.jl @@ -5,7 +5,6 @@ using JuliaFEM using JuliaFEM.Preprocess using JuliaFEM.Postprocess using JuliaFEM.Testing -using JuliaFEM.Abaqus: create_surface_elements datadir = first(splitext(basename(@__FILE__)))