julia v0.5 compatibility. test -> testing. new elements tri7 and wedge6. abaqus inp reading. more integration rules.

This commit is contained in:
Jukka Aho
2016-07-10 04:26:21 +03:00
parent a4e4347fec
commit a75aaecc97
89 changed files with 969 additions and 801 deletions
+1 -1
View File
@@ -4,4 +4,4 @@ ForwardDiff
LightXML
HDF5
JLD
Compat
+24 -11
View File
@@ -6,8 +6,6 @@ This is JuliaFEM -- Finite Element Package
"""
module JuliaFEM
using Compat
import Compat.String
importall Base
include("fields.jl")
@@ -18,13 +16,15 @@ export AbstractPoint, Point, IntegrationPoint, IP, Node
### ELEMENTS ###
include("elements.jl") # common element routines
export Node, AbstractElement, Element, update!, get_connectivity, get_basis, get_dbasis, inside, get_local_coordinates
include("elements_lagrange_macro.jl") # Continuous Galerkin (Lagrange) elements generated using macro
include("elements_lagrange.jl") # Continuous Galerkin (Lagrange) elements
export get_reference_coordinates, get_interpolation_polynomial
export Poi1,
Seg2, Seg3,
Tri3, Tri6, Quad4, Quad8, Quad9,
Tet4, Tet10, Hex8, Hex20, Hex27
Tri3, Tri6, Tri7,
Quad4, Quad8, Quad9,
Tet4, Tet10,
Wedge6,
Hex8, Hex20, Hex27
include("elements_nurbs.jl")
export NSeg, NSurf, NSolid, is_nurbs
@@ -59,7 +59,7 @@ end
### ASSEMBLY + SOLVE ###
include("assembly.jl")
include("solver_utils.jl")
include("solvers_utils.jl")
include("solvers.jl")
export AbstractSolver, Solver, Nonlinear, NonlinearSolver, Linear, LinearSolver,
get_unknown_field_name, get_formulation_type, get_problems,
@@ -91,10 +91,12 @@ include("problems_contact_3d.jl")
include("problems_contact_2d_autodiff.jl")
export Contact
#=
module API
include("api.jl")
# export ....
end
=#
module Preprocess
include("preprocess.jl")
@@ -106,8 +108,8 @@ export create_elements, Mesh,
find_nearest_nodes,
reorder_element_connectivity!
include("preprocess_abaqus_reader.jl")
include("preprocess_abaqus_reader_old.jl")
export parse_abaqus, parse_section, parse_element_section
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!,
@@ -115,11 +117,11 @@ export aster_create_elements, parse_aster_med_file, is_aster_mail_keyword,
filter_by_element_set, filter_by_element_id, MEDFile
end
function get_mesh(mesh_name::String, args...; kwargs...)
function get_mesh(mesh_name::AbstractString, args...; kwargs...)
return get_mesh(Val{Symbol(mesh_name)}, args...; kwargs...)
end
function get_model(model_name::String, args...; kwargs...)
function get_model(model_name::AbstractString, args...; kwargs...)
return get_model(Val{Symbol(model_name)}, args...; kwargs...)
end
@@ -136,8 +138,15 @@ export XDMF, xdmf_new_result!, xdmf_save_field!, xdmf_save!
end
export Postprocessor
# This connects model from preprocess_abaqus_reader to
# other JuliaFEM ecosystem and solves problem.
module Abaqus
include("abaqus.jl")
export abaqus_read_model
end
""" JuliaFEM testing routines. """
module Test
module Testing
if VERSION >= v"0.5-"
using Base.Test
else
@@ -148,12 +157,16 @@ export @test, @testset, @test_throws
#include("test.jl")
end
#=
module MaterialModels
include("vonmises.jl")
end
=#
#=
module Interfaces
include("interfaces.jl")
end
=#
end # module
+386
View File
@@ -0,0 +1,386 @@
# This file is a part of JuliaFEM.
# License is MIT: see https://github.com/JuliaFEM/JuliaFEM.jl/blob/master/LICENSE.md
importall Base
using JuliaFEM.Preprocess
global const ABAQUS_SECTIONS = [
"HEADING", "NODE", "ELEMENT", "SOLID SECTION",
"MATERIAL", "NSET", "SURFACE", "STEP"]
global const ABAQUS_SUBSECTIONS = [
"ELASTIC", "DENSITY", "SPECIFIC HEAT", "CONDUCTIVITY",
"STATIC", "BOUNDARY", "DSLOAD", "OUTPUT", "NODE FILE",
"RESTART", "END STEP"]
abstract AbstractMaterial
abstract AbstractProperty
abstract AbstractStep
type Model
mesh :: Mesh
materials :: Dict
properties :: Vector
steps :: Vector
end
function Model()
return Model(Mesh(), Dict(), Vector(), Vector())
end
function push!(model::Model, property::AbstractProperty)
push!(model.properties, property)
end
function push!(model::Model, step::AbstractStep)
push!(model.steps, step)
end
###
type Keyword
name
options
end
function Keyword()
return Keyword(nothing, nothing)
end
function getindex(kw::Keyword, s)
return parse(Dict(kw.options)[s])
end
type AbaqusReaderState
section
subsection
material
property
step
data
end
function parse(s::AbaqusReaderState)
data = []
for row in s.data
col = split(row, ',')
col = map(parse, col)
push!(data, col)
end
return data
end
function AbaqusReaderState()
return AbaqusReaderState(Keyword(), Keyword(), nothing, nothing, nothing, [])
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_options = []
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)
elseif length(pair) == 2
push!(keyword_options, pair[1] => pair[2])
else
error("Keyword failure: $line, $option, $pair")
end
end
return Keyword(keyword_name, keyword_options)
end
function is_new_section(line)
is_keyword(line) || return false
section = parse_keyword(line)
section.name in ABAQUS_SECTIONS || return false
return true
end
function is_new_subsection(line)
is_keyword(line) || return false
subsection = parse_keyword(line)
subsection.name in ABAQUS_SUBSECTIONS || return false
return true
end
function maybe_open_section!(model, state)
section_name = Val{Symbol(state.section.name)}
args = Tuple{Model, AbaqusReaderState, Type{section_name}}
if method_exists(open_section!, args)
info("Opening section $(state.section.name)")
open_section!(model, state, section_name)
end
end
function maybe_close_section!(model, state)
section_name = Val{Symbol(state.section.name)}
args = Tuple{Model, AbaqusReaderState, Type{section_name}}
if method_exists(close_section!, args)
info("Closing section $(state.section.name)")
close_section!(model, state, section_name)
end
end
function new_section!(model, state, line::AbstractString)
maybe_close_subsection!(model, state)
maybe_close_section!(model, state)
state.data = []
state.section = parse_keyword(line)
state.subsection = Keyword()
info("New section: $(state.section.name) with options $(state.section.options)")
maybe_open_section!(model, state)
end
function maybe_open_subsection!(model, state)
section_name = Val{Symbol(state.section.name)}
subsection_name = Val{Symbol(state.subsection.name)}
args = Tuple{Model, AbaqusReaderState, Type{section_name}, Type{subsection_name}}
if method_exists(open_subsection!, args)
info("Opening subsection $(state.section.name) / $(state.subsection.name)")
open_subsection!(model, state, section_name, subsection_name)
end
end
function maybe_close_subsection!(model, state)
section_name = Val{Symbol(state.section.name)}
subsection_name = Val{Symbol(state.subsection.name)}
args = Tuple{Model, AbaqusReaderState, Type{section_name}, Type{subsection_name}}
if method_exists(close_subsection!, args)
info("Closing subsection $(state.section.name) / $(state.subsection.name)")
close_subsection!(model, state, section_name, subsection_name)
end
end
function new_subsection!(model, state, line::AbstractString)
maybe_close_subsection!(model, state)
state.data = []
state.subsection = parse_keyword(line)
info("New subsection: $(state.subsection.name) with options $(state.subsection.options)")
maybe_open_subsection!(model, state)
end
# open_section! and open_subsection! are called right after keyword is found
function open_section! end
function open_subsection! end
# close_section! and close_subsection! are called at the end or section or before new keyword
function close_section! end
function close_subsection! end
function process_line!(model, state, line)
if state.section.name == nothing
info("unknown section, line = $line")
return
end
if is_keyword(line)
warn("missing keyword..? $line")
info("($(state.section.name), $(state.subsection.name)) => $line")
return
end
push!(state.data, line)
end
function abaqus_read_model(fn; read_mesh=true)
model = Model()
if read_mesh
model.mesh = abaqus_read_mesh(fn)
else
model.mesh = Mesh()
end
state = AbaqusReaderState()
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)
elseif is_new_subsection(line)
new_subsection!(model, state, line)
else
process_line!(model, state, line)
end
end
maybe_close_subsection!(model, state)
maybe_close_section!(model, state)
close(fid)
return model
end
### Model parse start
## Properties
type SolidSection <: AbstractProperty
element_set
material
end
function close_section!(model, state, ::Type{Val{Symbol("SOLID SECTION")}})
property = SolidSection(state.section["ELSET"], state.section["MATERIAL"])
push!(model, property)
end
## Materials
abstract MaterialProperty
type Elastic <: MaterialProperty
E
nu
end
type Material <: AbstractMaterial
name
properties
end
function Material(name)
return Material(name, [])
end
function push!(material::Material, property::MaterialProperty)
push!(material.properties, property)
end
function open_section!(model, state, ::Type{Val{:MATERIAL}})
state.material = Material(state.section["NAME"])
end
function close_subsection!(model, state, ::Type{Val{:MATERIAL}}, ::Type{Val{:ELASTIC}})
E, nu = parse(state)[1]
push!(state.material, Elastic(E, nu))
end
function close_section!(model, state, ::Type{Val{:MATERIAL}})
material_name = state.material.name
if haskey(model.materials, material_name)
warn("Material $material_name already exists in model, skipping definition.")
else
model.materials[material_name] = state.material
end
end
## Steps
type Step <: AbstractStep
content :: Vector
end
function push!(step::Step, data)
push!(step.content, data)
end
abstract AbstractBoundaryCondition
type Boundary <: AbstractBoundaryCondition
data :: Vector
end
function getindex(b::Boundary, j::Int64)
return b.data[j]
end
type DSLoad <: AbstractBoundaryCondition
data :: Vector
end
function getindex(l::DSLoad, j::Int64)
return l.data[j]
end
function open_section!(model, state, ::Type{Val{:STEP}})
state.step = Step([])
end
function close_subsection!(model, state, ::Type{Val{:STEP}}, ::Type{Val{:BOUNDARY}})
push!(state.step, Boundary(parse(state)))
end
function close_subsection!(model, state, ::Type{Val{:STEP}}, ::Type{Val{:DSLOAD}})
push!(state.step, DSLoad(parse(state)))
end
function close_section!(model, state, ::Type{Val{:STEP}})
push!(model.steps, state.step)
end
### model parse end
# when model is called, run simulation
function determine_problem_type(model, element_set_name)
return Elasticity
end
function determine_problem_dimension(model, element_set_name)
return 3
end
function call(model::Model)
info("Starting JuliaFEM-ABAQUS solver.")
# 1. create field problems and add elements
field_problems = []
for (element_set_name, element_ids) in model.mesh.element_sets
problem_type = determine_problem_type(model, element_set_name)
problem_name = "BODY $element_set_name"
problem_dimension = determine_problem_dimension(model, element_set_name)
problem = Problem(problem_type, problem_name, problem_dimension)
problem.elements = create_elements(model.mesh, element_set_name)
section = get_element_section(element_set_name)
material = get_material(section.material)
update!(problem, material)
push!(field_problems, problem)
end
# 2. loop steps
for step in model.steps
boundary_problems = []
for bc in step.content
if isa(bc, Boundary)
problem = Problem(Dirichlet, "fix nodes", 3, "displacement")
for (bc_name, dof) in bc.data
nodes = model.mesh.node_sets[bc_name]
for node in nodes
fix_node!(problem, node => dof)
end
end
push!(boundary_problems, problem)
end
if isa(bc, DSLoad)
problem = Problem(Elasticity, "pressure load", 3, "displacement")
for (bc_name, bc_type, pressure) in bc.data
elements = create_elements_from_surface_set(bc_name)
update!(elements, "surface pressure", pressure)
problem.elements = [problem.elements; elements]
end
push!(boundary_problems, problem)
end
end
all_problems = [problems; boundary_problems]
solver = Solver(solver_type, solver_description, all_problems...)
solver()
end
end
+28 -28
View File
@@ -7,7 +7,7 @@ type Element{E<:AbstractElement}
id :: Int
connectivity :: Vector{Int}
integration_points :: Vector{IP}
fields :: Dict{String, Field}
fields :: Dict{AbstractString, Field}
properties :: E
end
@@ -17,15 +17,15 @@ function Element{E<:AbstractElement}(::Type{E}, connectivity=[], integration_poi
return element
end
function getindex(element::Element, field_name::String)
function getindex(element::Element, field_name::AbstractString)
return element.fields[field_name]
end
function setindex!(element::Element, data::Field, field_name::String)
function setindex!(element::Element, data::Field, field_name)
element.fields[field_name] = data
end
function setindex!(element::Element, data::Function, field_name::String)
function setindex!(element::Element, data::Function, field_name)
if method_exists(data, Tuple{Element, Vector, Float64})
# create enclosure to pass element as argument
function wrapper_(ip, time)
@@ -38,34 +38,34 @@ function setindex!(element::Element, data::Function, field_name::String)
element.fields[field_name] = field
end
function setindex!(element::Element, data, field_name::String)
function setindex!(element::Element, data, field_name)
element.fields[field_name] = Field(data)
end
function call(element::Element, field_name::String)
function call(element::Element, field_name)
return element[field_name]
end
function call(element::Element, field_name::String, time)
function call(element::Element, field_name, time)
return element[field_name](time)
end
function last(element::Element, field_name::String)
function last(element::Element, field_name::AbstractString)
return last(element[field_name])
end
function call(element::Element, ip, time=0.0)
function call(element::Element, ip, time::Float64=0.0)
return get_basis(element, ip, time)
end
function call(element::Element, ip, time, ::Type{Val{:Jacobian}})
function call(element::Element, ip, time::Float64, ::Type{Val{:Jacobian}})
X = element["geometry"](time)
dN = get_dbasis(element, ip, time)
J = sum([kron(dN[:,i], X[i]') for i=1:length(X)])
return J
end
function call(element::Element, ip, time, ::Type{Val{:detJ}})
function call(element::Element, ip, time::Float64, ::Type{Val{:detJ}})
J = element(ip, time, Val{:Jacobian})
n, m = size(J)
if n == m # volume element
@@ -79,12 +79,12 @@ function call(element::Element, ip, time, ::Type{Val{:detJ}})
end
end
function call(element::Element, ip, time, ::Type{Val{:Grad}})
function call(element::Element, ip, time::Float64, ::Type{Val{:Grad}})
J = element(ip, time, Val{:Jacobian})
return inv(J)*get_dbasis(element, ip, time)
end
function call(element::Element, field_name::String, ip, time, ::Type{Val{:Grad}})
function call(element::Element, field_name::AbstractString, ip, time::Float64, ::Type{Val{:Grad}})
return element(ip, time, Val{:Grad})*element[field_name](time)
end
@@ -96,12 +96,12 @@ function call(element::Element, field::DCTI, time)
return field.data
end
function call(element::Element, field_name::String, time)
function call(element::Element, field_name::AbstractString, time)
field = element[field_name]
return element(field, time)
end
function call(element::Element, field_name::String, ip, time::Float64)
function call(element::Element, field_name::AbstractString, ip, time::Float64)
field = element[field_name]
return element(field, ip, time)
end
@@ -129,7 +129,7 @@ function call(element::Element, field::Field, ip, time::Float64)
return sum([field_[i]*basis[i] for i=1:n])
end
function size(element::Element, dim::Int)
function size(element::Element, dim)
return size(element)[dim]
end
@@ -144,17 +144,17 @@ julia> update!(element, "geometry", data)
As a result element now have time invariant (variable) vector field "geometry" with data ([0.0, 0.0], [1.0, 2.0]).
"""
function update!(element::Element, field_name::String, data::Dict)
function update!(element::Element, field_name, data::Dict)
element[field_name] = [data[i] for i in get_connectivity(element)]
end
function update!{K,V}(element::Element, field_name::String, data::Pair{Float64, Dict{K, V}})
function update!{K,V}(element::Element, field_name, data::Pair{Float64, Dict{K, V}})
time, field_data = data
element_data = V[field_data[i] for i in get_connectivity(element)]
update!(element, field_name, time => element_data)
end
function update!(element::Element, field_name::String, datas::Union{Real, Vector, Pair{Float64, Union{Float64, Real, Vector{Any}}}}...)
function update!(element::Element, field_name::AbstractString, datas::Union{Real, Vector, Pair{Float64, Union{Float64, Real, Vector{Any}}}}...)
for data in datas
if haskey(element, field_name)
update!(element[field_name], data)
@@ -168,13 +168,13 @@ function update!(element::Element, field_name::String, datas::Union{Real, Vector
end
end
function update!(element::Element, field_name::String, datas::Pair...)
function update!(element::Element, field_name, datas::Pair...)
for data in datas
update!(element, field_name, data)
end
end
function update!(element::Element, field_name::String, data::Pair{Float64, Vector{Any}})
function update!(element::Element, field_name, data::Pair{Float64, Vector{Any}})
if haskey(element, field_name)
update!(element[field_name], data)
else
@@ -182,7 +182,7 @@ function update!(element::Element, field_name::String, data::Pair{Float64, Vecto
end
end
function update!(element::Element, field_name::String, data::Pair{Float64, Vector{Int64}})
function update!(element::Element, field_name, data::Pair{Float64, Vector{Int64}})
if haskey(element, field_name)
update!(element[field_name], data)
else
@@ -190,7 +190,7 @@ function update!(element::Element, field_name::String, data::Pair{Float64, Vecto
end
end
function update!(element::Element, field_name::String, data::Pair{Float64, Vector{Vector{Float64}}})
function update!(element::Element, field_name, data::Pair{Float64, Vector{Vector{Float64}}})
if haskey(element, field_name)
update!(element[field_name], data)
else
@@ -198,7 +198,7 @@ function update!(element::Element, field_name::String, data::Pair{Float64, Vecto
end
end
function update!(element::Element, field_name::String, data::Pair{Float64, Float64})
function update!(element::Element, field_name, data::Pair{Float64, Float64})
if haskey(element, field_name)
update!(element[field_name], data)
else
@@ -206,7 +206,7 @@ function update!(element::Element, field_name::String, data::Pair{Float64, Float
end
end
function update!(element::Element, field_name::String, data::Union{Float64, Vector})
function update!(element::Element, field_name::AbstractString, data::Union{Float64, Vector})
if haskey(element, field_name)
update!(element[field_name], data)
else
@@ -228,15 +228,15 @@ function update!(element::Element, datas::Pair...)
end
end
function update!(element::Element, field_name::String, data::Function)
function update!(element::Element, field_name, data::Function)
element[field_name] = data
end
function update!(element::Element, field_name::String, field::Field)
function update!(element::Element, field_name, field::Field)
element[field_name] = field
end
function update!(elements::Vector, field_name::String, data)
function update!(elements::Vector, field_name, data)
for element in elements
update!(element, field_name, data)
end
+86 -2
View File
@@ -22,7 +22,7 @@ function get_basis(element::Element{Poi1}, ip, time)
return [1]
end
function call(element::Element{Poi1}, ip, time, ::Type{Val{:detJ}})
function call(element::Element{Poi1}, ip, time::Float64, ::Type{Val{:detJ}})
return 1.0
end
@@ -180,6 +180,47 @@ end
#
type Tri7 <: AbstractElement
end
function description(::Type{Tri7})
"7 node triangle"
end
function size(element::Element{Tri7})
return (2, 7)
end
function length(element::Element{Tri7})
return 7
end
function get_reference_coordinates(::Type{Tri7})
Vector{Float64}[
[0.0, 0.0], # N1
[1.0, 0.0], # N2
[0.0, 1.0], # N3
[0.5, 0.0], # N4
[0.5, 0.5], # N5
[0.0, 0.5], # N6
[1/3, 1/3]] # N7
end
function get_interpolation_polynomial(::Type{Tri7}, xi)
[
1 xi[1] xi[2] xi[1]^2 xi[1]*xi[2] xi[2]^2 xi[1]^2*xi[2]^2
]
end
function get_interpolation_polynomial(::Type{Tri7}, xi, ::Type{Val{:partial_derivatives}})
[
0 1 0 2*xi[1] xi[2] 0 2*xi[1]*xi[2]^2
0 0 1 0 xi[1] 2*xi[2] 2*xi[1]^2*xi[2]
]
end
#
type Quad4 <: AbstractElement
end
@@ -387,6 +428,47 @@ end
#
type Wedge6 <: AbstractElement
end
function description(::Type{Wedge6})
"6 node prismatic element (wedge)"
end
function size(element::Element{Wedge6})
return (3, 6)
end
function length(element::Element{Wedge6})
return 6
end
function get_reference_coordinates(::Type{Wedge6})
Vector{Float64}[
[0.0, 0.0, -1.0], # N1
[1.0, 0.0, -1.0], # N2
[0.0, 1.0, -1.0], # N3
[0.0, 0.0, 1.0], # N4
[1.0, 0.0, 1.0], # N5
[0.0, 1.0, 1.0]] # N6
end
function get_interpolation_polynomial(::Type{Wedge6}, x)
[
1 x[1] x[2] x[3] x[1]*x[3] x[2]*x[3]
]
end
function get_interpolation_polynomial(::Type{Wedge6}, x, ::Type{Val{:partial_derivatives}})
[
0 1 0 0 x[3] 0
0 0 1 0 0 x[3]
0 0 0 1 x[1] x[2]
]
end
#
type Hex8 <: AbstractElement
end
@@ -571,11 +653,13 @@ end
@create_basis Seg3
@create_basis Tri3
@create_basis Tri6
@create_basis Tri7
@create_basis Quad4
@create_basis Quad8
@create_basis Quad9
@create_basis Tet4
@create_basis Tet10
@create_basis Wedge6
@create_basis Hex8
@create_basis Hex20
@create_basis Hex27
@@ -585,7 +669,7 @@ function inside(::Union{Type{Seg2}, Type{Seg3}, Type{Quad4}, Type{Quad8},
return all(-1.0 .<= xi .<= 1.0)
end
function inside(::Union{Type{Tri3}, Type{Tri6}, Type{Tet4}, Type{Tet10}}, xi)
function inside(::Union{Type{Tri3}, Type{Tri6}, Type{Tri7}, Type{Tet4}, Type{Tet10}}, xi)
return all(xi .>= 0.0) && (sum(xi) <= 1.0)
end
-69
View File
@@ -1,69 +0,0 @@
# This file is a part of JuliaFEM.
# License is MIT: see https://github.com/JuliaFEM/JuliaFEM.jl/blob/master/LICENSE.md
# Lagrange (Continous Galerkin) finite elements shape functions generated using macro.
"""
Given polynomial P and coordinates of reference element, calculate
Lagrange basis functions
"""
function calculate_lagrange_basis_coefficients(P, X)
dim, nbasis = size(X)
A = zeros(nbasis, nbasis)
for i=1:nbasis
A[i,:] = P(X[:, i])
end
return inv(A)
end
function refcoords(X::Matrix)
return Vector{Float64}[X[:,i] for i=1:size(X,2)]
end
"""
Create new Lagrange element
Examples
--------
>>> @create_lagrange_element(Seg2, "2 node linear segment", X, P)
"""
macro create_lagrange_element(element_name, element_description, X, P)
eltype = esc(element_name)
quote
global get_basis, length, size, get_reference_coordinates
#=
get_reference_element_coordinates,
get_reference_element_midpoint
=#
type $eltype <: AbstractElement
end
A = calculate_lagrange_basis_coefficients($P, $X)
#basis(xi) = C*$P(xi)
function get_basis(element::Element{$eltype}, ip, time)
return transpose($P(ip))*A
end
function size(element::Element{$eltype})
return size($X)
end
function length(element::Element{$eltype})
return size($X, 2)
end
XX = refcoords($X)
function get_reference_coordinates(::Type{$eltype})
return XX
end
end
end
# 3d Lagrange elements
function get_reference_element_midpoint{E}(element::Element{E})
get_reference_element_midpoint(E)
end
+1 -1
View File
@@ -15,7 +15,7 @@ type Field{A<:Union{Discrete,Continuous}, B<:Union{Constant,Variable}, C<:Union{
data
end
typealias FieldSet Dict{String, Field}
typealias FieldSet Dict{AbstractString, Field}
### Basic data structure for discrete field
+19 -8
View File
@@ -58,14 +58,10 @@ end
### "cartesian" elements, integration rules comes from tensor product
### 0d elements
function get_integration_points(element::Poi1)
[ (1.0, [] ) ]
end
### 1d elements
typealias CartesianLineElement Union{Seg2, Seg3, NSeg}
typealias CartesianSurfaceElement Union{Quad4, Quad8, Quad9, NSurf}
typealias CartesianVolumeElement Union{Hex8, Hex20, Hex27, NSolid}
@@ -90,7 +86,7 @@ end
# http://math2.uncc.edu/~shaodeng/TEACHING/math5172/Lectures/Lect_15.PDF
# http://libmesh.github.io/doxygen/quadrature__gauss__2D_8C_source.html
typealias TriangularElement Union{Tri3, Tri6}
typealias TriangularElement Union{Tri3, Tri6, Tri7}
function get_integration_points(element::TriangularElement, ::Type{Val{1}})
weights = [0.5]
@@ -229,16 +225,31 @@ function get_integration_points(element::TetrahedralElement, ::Type{Val{4}})
return zip(weights, points)
end
function get_integration_points(element::Union{TriangularElement, TetrahedralElement}, order::Int64)
typealias PrismaticElement Union{Wedge6}
function get_integration_points(element::PrismaticElement, ::Type{Val{2}})
weights = 1/6*[1.0, 1.0, 1.0, 1.0, 1.0, 1.0]
points = Vector{Float64}[
[0.5, 0.0, -1.0/sqrt(3)],
[0.0, 0.5, -1.0/sqrt(3)],
[0.5, 0.5, -1.0/sqrt(3)],
[0.5, 0.0, 1.0/sqrt(3)],
[0.0, 0.5, 1.0/sqrt(3)],
[0.5, 0.5, 1.0/sqrt(3)]]
return zip(weights, points)
end
function get_integration_points(element::Union{TriangularElement,
TetrahedralElement, PrismaticElement}, order::Int64)
return get_integration_points(element, Val{order})
end
### default number of integration points for each element
### 2 for linear elements, 3 for quadratic
typealias LinearElement Union{Seg2, Tri3, Quad4, Tet4, Hex8}
typealias LinearElement Union{Seg2, Tri3, Quad4, Tet4, Wedge6, Hex8}
typealias QuadraticElement Union{Seg3, Tri6, Tet10, Quad8, Quad9, Hex20, Hex27}
typealias QuadraticElement Union{Seg3, Tri6, Tri7, Tet10, Quad8, Quad9, Hex20, Hex27}
function get_integration_order(element::LinearElement)
return 2
+13 -2
View File
@@ -129,7 +129,7 @@ function copy_field!(src_problem::Problem, dst_problem::Problem, field_name, tim
end
""" Return field calculated to nodal points for elements in problem p. """
function call(problem::Problem, field_name::String, time::Float64=0.0)
function call(problem::Problem, field_name::AbstractString, time::Float64=0.0)
f = Dict()
for element in get_elements(problem)
for (c, v) in zip(get_connectivity(element), element(field_name, time))
@@ -143,7 +143,7 @@ function call(problem::Problem, field_name::String, time::Float64=0.0)
end
""" Interpolate field from a set of elements. """
function call(problem::Problem, field_name::String, X::Vector, time::Float64=0.0; fillna=NaN)
function call(problem::Problem, field_name::AbstractString, X::Vector, time::Float64=0.0; fillna=NaN)
for element in get_elements(problem)
if inside(element, X, time)
xi = get_local_coordinates(element, X, time)
@@ -153,3 +153,14 @@ function call(problem::Problem, field_name::String, X::Vector, time::Float64=0.0
return fillna
end
""" Interpolate field from a set of elements. """
function call(problem::Problem, field_name::AbstractString, X::Vector, time::Float64, ::Type{Val{:Grad}}; fillna=NaN)
for element in get_elements(problem)
if inside(element, X, time)
xi = get_local_coordinates(element, X, time)
return element(field_name, xi, time, Val{:Grad})
end
end
return fillna
end
+3 -3
View File
@@ -100,7 +100,7 @@ function xdmf_new_result!(xdmf::XDMF, elements::Vector, time)
set_attribute(dataitem, "DataType", "Float")
set_attribute(dataitem, "Format", "XML")
#set_attribute(dataitem, "Precision", 8)
s = String[]
s = []
ndim = 0
for i in xdmf.permutation
ndim += length(X[i])
@@ -117,7 +117,7 @@ function xdmf_new_result!(xdmf::XDMF, elements::Vector, time)
set_attribute(dataitem, "Format", "XML")
set_attribute(dataitem, "DataType", "Int")
# set_attribute(dataitem, "Precision", 8)
s = String[]
s = []
eldim = 0
for element in elements
eltype = get_xdmf_element_code(element)
@@ -167,7 +167,7 @@ function xdmf_save_field!(xdmf, elements::Vector, time, field_name; field_type="
#set_attribute(dataitem, "Precision", 8)
debug && info("field dim = $field_dim")
debug && info(f)
s = String[]
s = []
dim = 0
for i in xdmf.permutation
gi = zeros(field_dim)
+34 -24
View File
@@ -18,14 +18,17 @@ using JuliaFEM
type Mesh
nodes :: Dict{Int64, Vector{Float64}}
node_sets :: Dict{String, Set{Int64}}
node_sets :: Dict{Symbol, Set{Int64}}
elements :: Dict{Int64, Vector{Int64}}
element_types :: Dict{Int64, Symbol}
element_sets :: Dict{String, Set{Int64}}
element_codes :: Dict{Int64, Symbol}
element_sets :: Dict{Symbol, Set{Int64}}
surfaces :: Dict{Symbol, Vector{Tuple{Int64, Symbol}}}
surface_types :: Dict{Symbol, Symbol}
end
function Mesh()
return Mesh(Dict(), Dict(), Dict(), Dict(), Dict())
return Mesh(Dict(), Dict(), Dict(), Dict(), Dict(), Dict(), Dict(), Dict())
end
function add_node!(mesh::Mesh, nid::Int, ncoords::Vector{Float64})
@@ -38,7 +41,7 @@ function add_nodes!(mesh::Mesh, nodes::Dict{Int64, Vector{Float64}})
end
end
function add_node_to_node_set!(mesh::Mesh, set_name::String, nids...)
function add_node_to_node_set!(mesh::Mesh, set_name, nids...)
if !haskey(mesh.node_sets, set_name)
mesh.node_sets[set_name] = Set{Int64}()
end
@@ -56,7 +59,7 @@ function add_elements!(mesh::Mesh, elements::Dict{Int64, Tuple{Symbol, Vector{In
end
end
function add_element_to_element_set!(mesh::Mesh, set_name::String, elids...)
function add_element_to_element_set!(mesh::Mesh, set_name, elids...)
if !haskey(mesh.element_sets, set_name)
mesh.element_sets[set_name] = Set{Int64}()
end
@@ -84,38 +87,45 @@ function filter_by_element_id(mesh::Mesh, element_ids::Vector{Int64})
return mesh2
end
function filter_by_element_set(mesh::Mesh, set_name::String)
function filter_by_element_set(mesh::Mesh, set_name)
filter_by_element_id(mesh::Mesh, collect(mesh.element_sets[set_name]))
end
function create_elements(mesh::Mesh)
elements = [Element(JuliaFEM.(mesh.element_types[elid]), elcon) for (elid, elcon) in mesh.elements]
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
elements = [Element(JuliaFEM.(mesh.element_types[id]), mesh.elements[id]) for id in element_ids]
update!(elements, "geometry", mesh.nodes)
return elements
end
function create_elements(mesh::Mesh, element_sets::String...)
elements = Element[]
for element_set in element_sets
new_elements = create_elements(filter_by_element_set(mesh, element_set))
elements = [elements; new_elements]
function create_elements(mesh::Mesh, element_sets::Symbol...; element_type=nothing)
if isempty(element_sets)
element_ids = collect(keys(mesh.elements))
else
element_ids = Set{Int64}()
for set_name in element_sets
element_ids = union(element_ids, mesh.element_sets[set_name])
end
end
if element_type != nothing
filter!(id -> mesh.element_types[id] == element_type, element_ids)
end
elements = [Element(JuliaFEM.(mesh.element_types[id]), mesh.elements[id]) for id in element_ids]
update!(elements, "geometry", mesh.nodes)
return elements
end
function create_elements(mesh::Mesh, element_type::Symbol)
elements = Element[]
for (elid, elcon) in mesh.elements
eltype = mesh.element_types[elid]
eltype == element_type || continue
element = Element(JuliaFEM.(eltype), elcon)
update!(element, "geometry", mesh.nodes)
push!(elements, element)
end
return elements
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 form mesh and return id numbers as list. """
""" find npts nearest nodes from mesh and return id numbers as list. """
function find_nearest_nodes(mesh::Mesh, coords::Vector, npts=1)
dist = Dict{Int64, Float64}()
for (nid, c) in mesh.nodes
+53 -28
View File
@@ -79,7 +79,8 @@ end
Parse elements from input.
"""
function parse_section(model, lines, key, idx_start, idx_end, ::Type{Val{:ELEMENT}})
definition = uppercase(lines[idx_start])
#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})
@@ -121,7 +122,9 @@ 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])
#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")
@@ -146,28 +149,27 @@ function parse_section(model, lines, key, idx_start, idx_end, ::Union{Type{Val{:
end
"""
TODO ! Parse surface keyword
Parse SURFACE keyword
"""
function parse_section(model, lines, key, idx_start, idx_end,
::Type{Val{:SURFACE}})
function parse_section(model, lines, key, idx_start, idx_end, ::Type{Val{:SURFACE}})
info("Parsing surface")
definition = uppercase(lines[idx_start])
ids = Vector{Tuple(Int, Int)}()
#definition = uppercase(lines[idx_start])
definition = lines[idx_start]
has_set_def = match(r"TYPE=([\w\_\-]+),.*NAME=([\w\_\-]+)", definition)
has_set_def != nothing || return
set_type = Symbol(has_set_def[1])
set_name = Symbol(has_set_def[2])
data = Vector{Tuple{Int64, Symbol}}()
for line in lines[idx_start + 1: idx_end]
if !(empty_or_comment_line(line))
m = matchall(r"[-0-9.]+", line)
node_id = parse(Int, m[1])
coords = float(m[2:end])
nodes[node_id] = coords
model["nodes"][node_id] = coords
end
empty_or_comment_line(line) && continue
m = match(r"(?P<element_id>\d+),.+(?P<element_side>S\d+).*", line)
element_id = parse(Int, m[:element_id])
element_side = Symbol(m[:element_side])
push!(data, (element_id, element_side))
end
has_set_def = match(r"NSET=([\w\_\-]+)", definition)
if has_set_def != nothing
set_name = has_set_def[1]
model["nsets"][set_name] = ids
end
model["surface_types"][set_name] = set_type
model["surfaces"][set_name] = data
return
end
"""
@@ -181,7 +183,7 @@ function find_keywords(lines)
end
end
push!(indexes, length(lines) + 1)
indexes
return indexes
end
"""
@@ -195,21 +197,44 @@ function parse_abaqus(fid::IOStream)
parser::Function = x->()
model = Dict{AbstractString, Any}()
model["nodes"] = Dict{Int64, Vector{Float64}}()
model["nsets"] = Dict{String, Vector{Int64}}()
model["elsets"] = Dict{String, Vector{Int64}}()
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 = uppercase(lines[idx_start])
keyword = regex_match(r"\s*(\w+)", keyword_line, 1)
keyword = regex_match(r"\s*([\w ]+)", keyword_line, 1)
k_sym = Symbol(keyword)
if method_exists(parse_section, Tuple{Dict, Array{Integer, 1}, Symbol,
Integer, Integer, Type{Val{k_sym}}})
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
warn("Unknown section: $(keyword)")
# else
# warn("Unknown section: $(keyword)")
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.surfaces = model["surfaces"]
mesh.surface_types = model["surface_types"]
return mesh
end
-141
View File
@@ -1,141 +0,0 @@
# This file is a part of JuliaFEM.
# License is MIT: see https://github.com/JuliaFEM/JuliaFEM.jl/blob/master/LICENSE.md
global handlers = Dict()
"""
Register new handler for parser
"""
function add_handler(section, function_name)
handlers[section] = function_name
end
function create_or_get(model, key)
if !(key in keys(model))
model[key] = Dict()
end
return model[key]
end
function parse_header(header_line)
args = map(s -> strip(s), split(header_line, ","))
args[1] = strip(args[1], '*')
d = Dict("section" => args[1], "options" => Dict())
options = d["options"]
for k in args[2:end]
args2 = split(k, "=")
options[args2[1]] = args2[2]
end
return d
end
function parse_node_section(model, header, data)
nodes = create_or_get(model, "nodes")
for line in split(data, "\n")
m = matchall(r"[-0-9.]+", line)
id = parse(Int, m[1])
coords = float(m[2:end])
nodes[id] = coords
end
end
function parse_element_section(model, header, data)
info("Parsing elements")
eldims = Dict(
"C3D10" => 10,
"C3D4" => 4,
"S3" => 3,
"STRI65" => 6)
eltype = header["options"]["TYPE"]
if !(eltype in keys(eldims))
throw("Element $eltype dimension information missing")
end
eldim = eldims[eltype]
test_match = matchall(r"[0-9]+", "234, 242")
m = matchall(r"[0-9]+", data)
m = map((s) -> parse(Int, s), m)
elements = create_or_get(model, "elements")
m = reshape(m, eldim+1, round(Int, length(m)/(eldim+1)))
nel = size(m)[2]
info("$nel elements found")
for i=1:nel
elements[m[1,i]] = m[2:end,i]
end
if "ELSET" in keys(header["options"])
elsets = create_or_get(model, "elsets")
elset_name = header["options"]["ELSET"]
info("Creating ELSET $elset_name")
elsets[elset_name] = Int64[]
for i=1:nel
push!(elsets[elset_name], m[1,i])
end
end
end
function parse_elset_section(model, header, data)
elset_name = header["options"]["ELSET"]
info("Creating element set $elset_name")
m = matchall(r"[0-9]+", data)
element_ids = map((s) -> parse(Int, s), m)
elsets = create_or_get(model, "elsets")
elsets[elset_name] = Int64[]
for j in element_ids
push!(elsets[elset_name], j)
end
end
function parse_nodeset_section(model, header, data)
nset_name = header["options"]["NSET"]
info("Creating node set $nset_name")
m = matchall(r"[0-9]+", data)
node_ids = map((s) -> parse(Int, s), m)
nsets = create_or_get(model, "nsets")
nsets[nset_name] = Int64[]
for j in node_ids
push!(nsets[nset_name], j)
end
end
function parse_abaqus(fid::IOStream)
model = Dict()
section = nothing
header = nothing
data = String[]
info("Registered handlers: $(keys(handlers))")
function process_section(section)
if section == nothing
return
end
if !(section in keys(handlers))
info("Don't know what to do with data in section $section")
info("Skipping $(length(data)) bytes of unknown data")
return
end
joined = join(data, "")
handlers[section](model, header, strip(joined))
empty!(data)
end
line_idx = 0
for line in eachline(fid)
if startswith(line, "**")
continue
end
if startswith(line, "*")
process_section(section)
header = parse_header(line)
section = header["section"]
continue
end
push!(data, line)
end
process_section(section)
return model
end
# add handlers
add_handler("NODE", parse_node_section)
add_handler("ELEMENT", parse_element_section)
add_handler("NSET", parse_nodeset_section)
add_handler("ELSET", parse_elset_section)
+22 -209
View File
@@ -4,42 +4,7 @@
using HDF5
using JuliaFEM
function aster_create_elements(mesh, element_set, element_type=nothing; reverse_connectivity=false)
elements = Element[]
mapping = Dict(
:SE2 => Seg2,
:TR3 => Tri3,
:TR6 => Tri6,
:QU4 => Quad4,
:HE8 => Hex8,
:TE4 => Tet4,
:T10 => Tet10)
for (elid, (eltype, elset, elcon)) in mesh["connectivity"]
elset == element_set || continue
if !isa(element_type, Void)
if isa(element_type, Tuple)
if !(eltype in element_type)
continue
end
elseif eltype != element_type
continue
end
end
if reverse_connectivity
elcon = reverse(elcon)
end
if !haskey(mapping, eltype)
error("aster_create_elements: unknown element mapping $eltype")
end
element = Element(mapping[eltype], elcon)
push!(elements, element)
end
update!(elements, "geometry", mesh["nodes"])
return elements
end
function aster_parse_nodes(section::String; strip_characters=true)
function aster_parse_nodes(section; strip_characters=true)
nodes = Dict{Any, Vector{Float64}}()
has_started = false
for line in split(section, '\n')
@@ -68,10 +33,10 @@ function aster_parse_nodes(section::String; strip_characters=true)
return nodes
end
function parse(mesh::String, ::Type{Val{:CODE_ASTER_MAIL}})
model = Dict{String, Any}()
function parse(mesh, ::Type{Val{:CODE_ASTER_MAIL}})
model = Dict()
header = nothing
data = String[]
data = []
for line in split(mesh, '\n')
length(line) != 0 || continue
info("line: $line")
@@ -90,151 +55,6 @@ function parse(mesh::String, ::Type{Val{:CODE_ASTER_MAIL}})
end
function aster_renumber_nodes_!(mesh, node_numbering)
old_nodes = mesh["nodes"]
new_nodes = typeof(old_nodes)()
for (node_id, node_coords) in old_nodes
new_node_id = node_numbering[node_id]
new_nodes[new_node_id] = node_coords
end
mesh["nodes"] = new_nodes
for (elid, (eltype, elset, elcon)) in mesh["connectivity"]
new_elcon = [node_numbering[node_id] for node_id in elcon]
mesh["connectivity"][elid] = (eltype, elset, new_elcon)
end
end
function aster_renumber_nodes(mesh)
nodemap = Dict{Int64,Int64}()
for (i, nid) in enumerate(keys(mesh["nodes"]))
nodemap[nid] = i
end
new_nodes = Dict{Int64, Vector{Float64}}()
for (nid, ncoords) in mesh["nodes"]
new_nodes[nodemap[nid]] = ncoords
end
function change_node_ids(old_ids::Vector{Int64})
return Int[nodemap[nid] for nid in old_ids]
end
new_elements = Dict{Int64, Tuple{Symbol, Symbol, Vector{Int64}}}()
for (elid, (eltype, elset, elcon)) in mesh["connectivity"]
new_elements[elid] = (eltype, elset, change_node_ids(elcon))
end
mesh["nodes"] = new_nodes
mesh["elements"] = new_elements
return mesh
end
function aster_renumber_nodes!(mesh1, mesh2)
reserved_node_ids = Set(collect(keys(mesh1["nodes"])))
mesh2_node_numbering = Dict{Int64, Int64}()
# find new node ids assigned for mesh 2
k = 1
for node_id in sort(collect(keys(mesh2["nodes"])))
# if node id is reserved in mesh 1, find new number
if node_id in reserved_node_ids
while k in reserved_node_ids
k += 1
end
mesh2_node_numbering[node_id] = k
push!(reserved_node_ids, k)
else
mesh2_node_numbering[node_id] = node_id
end
end
aster_renumber_nodes_!(mesh2, mesh2_node_numbering)
#=
# create new nodes
mesh2_old_nodes = mesh2["nodes"]
mesh2_new_nodes = typeof(mesh2_old_nodes)()
for (node_id, node_coords) in mesh2_old_nodes
new_node_id = mesh2_node_numbering[node_id]
mesh2_new_nodes[new_node_id] = node_coords
end
mesh2["nodes"] = mesh2_new_nodes
# update connectivity
for (elid, (eltype, elset, elcon)) in mesh2["connectivity"]
new_elcon = [mesh2_node_numbering[node_id] for node_id in elcon]
mesh2["connectivity"][elid] = (eltype, elset, new_elcon)
end
=#
end
function aster_renumber_elements!(mesh1, mesh2)
reserved_element_ids = Set(collect(keys(mesh1["connectivity"])))
mesh2_element_numbering = Dict{Int64, Int64}()
# find new element ids assigned for mesh 2
k = 1
for element_id in sort(collect(keys(mesh2["connectivity"])))
# if node id is reserved in mesh 1, find new number
if element_id in reserved_element_ids
while k in reserved_element_ids
k += 1
end
mesh2_element_numbering[element_id] = k
push!(reserved_element_ids, k)
else
mesh2_element_numbering[element_id] = element_id
end
end
# create new elements
mesh2_old_elements = mesh2["connectivity"]
mesh2_new_elements = typeof(mesh2_old_elements)()
for (element_id, element_data) in mesh2_old_elements
new_element_id = mesh2_element_numbering[element_id]
mesh2_new_elements[new_element_id] = element_data
end
mesh2["connectivity"] = mesh2_new_elements
end
function aster_combine_meshes(mesh1, mesh2)
# check that meshes are ready to be combined
node_ids_mesh_1 = collect(keys(mesh1["nodes"]))
node_ids_mesh_2 = collect(keys(mesh2["nodes"]))
if length(intersect(node_ids_mesh_1, node_ids_mesh_2)) != 0
error("nodes with same id number in both meshes, failed.")
end
element_ids_mesh_1 = collect(keys(mesh1["connectivity"]))
element_ids_mesh_2 = collect(keys(mesh2["connectivity"]))
if length(intersect(element_ids_mesh_1, element_ids_mesh_2)) != 0
error("elements with same id number in both meshes, failed.")
end
@assert similar(mesh1) == similar(mesh2)
@assert similar(mesh1["nodes"]) == similar(mesh2["nodes"])
@assert similar(mesh1["connectivity"]) == similar(mesh2["connectivity"])
new_mesh = similar(mesh1)
new_mesh["nodes"] = similar(mesh1["nodes"])
new_mesh["connectivity"] = similar(mesh1["connectivity"])
for (node_id, node_coords) in mesh1["nodes"]
new_mesh["nodes"][node_id] = node_coords
end
for (node_id, node_coords) in mesh2["nodes"]
new_mesh["nodes"][node_id] = node_coords
end
for (element_id, element_data) in mesh1["connectivity"]
new_mesh["connectivity"][element_id] = element_data
end
for (element_id, element_data) in mesh2["connectivity"]
new_mesh["connectivity"][element_id] = element_data
end
return new_mesh
end
"""
Code Aster binary file (.med), which is exported from SALOME.
"""
@@ -242,7 +62,7 @@ type MEDFile
data :: Dict
end
function MEDFile(fn::String)
function MEDFile(fn)
MEDFile(h5read(fn, "/"))
end
@@ -316,14 +136,6 @@ function get_connectivity(med::MEDFile, elsets, mesh_name)
eltype = Symbol(eltype)
elco = element_connectivity[:, i]
elset = Symbol(elsets[elset_ids[i]])
#= to more general preprocess
if haskey(med_elmap, eltype)
elco = elco[med_elmap[eltype]]
else
warn("no element mapping info found for element type $eltype")
warn("consider this as a warning: element may have french nodal ordering")
end
=#
d[element_ids[i]] = (eltype, elset, elco)
end
end
@@ -334,9 +146,9 @@ end
Paramters
---------
fn :: String
fn
file name to parse
mesh_name :: String, optional
mesh_name :: optional
mesh name, if several meshes in one file
Returns
@@ -344,7 +156,7 @@ Returns
Dict containing fields "nodes" and "connectivity".
"""
function parse_aster_med_file(fn::String, mesh_name=nothing; debug=false)
function parse_aster_med_file(fn, mesh_name=nothing; debug=false)
med = MEDFile(fn)
mesh_names = get_mesh_names(med::MEDFile)
all_meshes = join(mesh_names, ", ")
@@ -364,7 +176,7 @@ function parse_aster_med_file(fn::String, mesh_name=nothing; debug=false)
end
nodes = get_nodes(med, nsets, mesh_name)
conn = get_connectivity(med, elsets, mesh_name)
result = Dict{String, Any}()
result = Dict("nodes" => nodes, "connectivity" => conn)
result["nodes"] = nodes
result["connectivity"] = conn
return result
@@ -380,11 +192,12 @@ end
# :Tet10 => [3, 2, 1, 4, 6, 5, 7, 10, 9, 8])
global const med_connectivity = Dict{Symbol, Vector{Int}}(
:Tet4 => [4,3,1,2],
:Tet10 => [4,3,1,2,10,7,8,9,6,5],
:Hex8 => [4,8,7,3,1,5,6,2],
:Hex20 => [4,8,7,3,1,5,6,2,20,15,19,11,12,16,14,10,17,13,18,9],
:Hex27 => [4,8,7,3,1,5,6,2,20,15,19,11,12,16,14,10,17,13,18,9,24,25,26,23,21,22,27])
:Tet4 => [4,3,1,2],
:Tet10 => [4,3,1,2,10,7,8,9,6,5],
:Wedge6 => [4,5,6,1,2,3],
:Hex8 => [4,8,7,3,1,5,6,2],
:Hex20 => [4,8,7,3,1,5,6,2,20,15,19,11,12,16,14,10,17,13,18,9],
:Hex27 => [4,8,7,3,1,5,6,2,20,15,19,11,12,16,14,10,17,13,18,9,24,25,26,23,21,22,27])
# element names in CA -> element names in JuliaFEM
global const mapping = Dict(
@@ -397,7 +210,7 @@ global const mapping = Dict(
:TR3 => :Tri3,
:TR6 => :Tri6,
:TR7 => :Tru6,
:TR7 => :Tri7,
:QU4 => :Quad4,
:QU8 => :Quad8,
@@ -406,9 +219,9 @@ global const mapping = Dict(
:TE4 => :Tet4,
:T10 => :Tet10,
:PE6 => :Penta6,
:P15 => :Penta15,
:P18 => :Penta18,
:PE6 => :Wedge6,
:P15 => :Wedge15,
:P18 => :Wedge18,
:HE8 => :Hex8,
:H20 => :Hex20,
@@ -419,17 +232,17 @@ global const mapping = Dict(
)
function aster_read_mesh(fn::String, mesh_name=nothing; reorder_element_connectivity=true)
function aster_read_mesh(fn, mesh_name=nothing; reorder_element_connectivity=true)
result = parse_aster_med_file(fn, mesh_name)
mesh = Mesh()
for (nid, (nset, ncoords)) in result["nodes"]
add_node!(mesh, nid, ncoords)
add_node_to_node_set!(mesh, string(nset), nid)
add_node_to_node_set!(mesh, nset, nid)
end
for (elid, (eltype, elset, elcon)) in result["connectivity"]
haskey(mapping, eltype) || error("Code Aster .med reader: element type $eltype not found from mapping")
add_element!(mesh, elid, mapping[eltype], elcon)
add_element_to_element_set!(mesh, string(elset), elid)
add_element_to_element_set!(mesh, elset, elid)
end
if reorder_element_connectivity
reorder_element_connectivity!(mesh, med_connectivity)
+4 -4
View File
@@ -84,9 +84,9 @@ function get_dofs(assembly::Assembly)
end
type Problem{P<:AbstractProblem}
name :: String # descriptive name for problem
name :: AbstractString # descriptive name for problem
dimension :: Int # degrees of freedom per node
parent_field_name :: String # (optional) name of parent field e.g. "displacement"
parent_field_name :: AbstractString # (optional) name of parent field e.g. "displacement"
elements :: Vector{Element}
dofmap :: Dict{Element, Vector{Int64}} # connects element local dofs to global dofs
assembly :: Assembly
@@ -103,7 +103,7 @@ julia> prob1 = Problem(Elasticity, "this is my problem", 3)
julia> prob2 = Problem(Elasticity, 3)
"""
function Problem{P<:FieldProblem}(::Type{P}, name::String, dimension::Int64)
function Problem{P<:FieldProblem}(::Type{P}, name::AbstractString, dimension::Int64)
Problem{P}(name, dimension, "none", [], Dict(), Assembly(), P())
end
function Problem{P<:FieldProblem}(::Type{P}, dimension::Int64)
@@ -280,7 +280,7 @@ function length(problem::Problem)
return length(problem.elements)
end
function update!(problem::Problem, field_name::String, field)
function update!(problem::Problem, field_name, field)
update!(problem.elements, field_name, field)
end
+1 -1
View File
@@ -19,7 +19,7 @@ type Contact <: BoundaryProblem
use_forwarddiff :: Bool
minimum_active_set_size :: Int
distval :: Float64
store_fields :: Vector{String}
store_fields :: Vector{AbstractString}
end
function Contact()
+14 -14
View File
@@ -38,7 +38,7 @@ type Elasticity <: FieldProblem
formulation :: Symbol
finite_strain :: Bool
geometric_stiffness :: Bool
store_fields :: Vector{String}
store_fields :: Vector{Symbol}
end
function Elasticity()
# formulations: plane_stress, plane_strain, continuum
@@ -139,11 +139,11 @@ function assemble{El<:Elasticity2DVolumeElements}(problem::Problem{Elasticity},
# calculate stress
stress_vec = D * ([1.0, 1.0, 2.0] .* strain_vec)
"strain" in props.store_fields && update!(ip, "strain", time => strain_vec)
"stress" in props.store_fields && update!(ip, "stress", time => stress_vec)
"stress 11" in props.store_fields && update!(ip, "stress 11", time => stress_vec[1])
"stress 22" in props.store_fields && update!(ip, "stress 22", time => stress_vec[2])
"stress 12" in props.store_fields && update!(ip, "stress 12", time => stress_vec[3])
:strain in props.store_fields && update!(ip, "strain", time => strain_vec)
:stress in props.store_fields && update!(ip, "stress", time => stress_vec)
:stress11 in props.store_fields && update!(ip, "stress11", time => stress_vec[1])
:stress22 in props.store_fields && update!(ip, "stress22", time => stress_vec[2])
:stress12 in props.store_fields && update!(ip, "stress12", time => stress_vec[3])
Km += w*BL'*D*BL
@@ -452,14 +452,14 @@ function assemble{El<:Elasticity3DVolumeElements}(problem::Problem{Elasticity},
0.0 0.0 0.0 0.0 0.0 0.5-nu]
stress_vec = D * ([1.0, 1.0, 1.0, 2.0, 2.0, 2.0].*strain_vec)
"strain" in props.store_fields && update!(ip, "strain", time => strain_vec)
"stress" in props.store_fields && update!(ip, "stress", time => stress_vec)
"stress 11" in props.store_fields && update!(ip, "stress 11", time => stress_vec[1])
"stress 22" in props.store_fields && update!(ip, "stress 22", time => stress_vec[2])
"stress 33" in props.store_fields && update!(ip, "stress 33", time => stress_vec[3])
"stress 12" in props.store_fields && update!(ip, "stress 12", time => stress_vec[4])
"stress 23" in props.store_fields && update!(ip, "stress 23", time => stress_vec[5])
"stress 13" in props.store_fields && update!(ip, "stress 13", time => stress_vec[6])
:strain in props.store_fields && update!(ip, "strain", time => strain_vec)
:stress in props.store_fields && update!(ip, "stress", time => stress_vec)
:stress11 in props.store_fields && update!(ip, "stress11", time => stress_vec[1])
:stress22 in props.store_fields && update!(ip, "stress22", time => stress_vec[2])
:stress33 in props.store_fields && update!(ip, "stress33", time => stress_vec[3])
:stress12 in props.store_fields && update!(ip, "stress12", time => stress_vec[4])
:stress23 in props.store_fields && update!(ip, "stress23", time => stress_vec[5])
:stress13 in props.store_fields && update!(ip, "stress13", time => stress_vec[6])
Km += w*BL'*D*BL
+47 -3
View File
@@ -44,8 +44,8 @@ https://en.wikipedia.org/wiki/Thermal_diffusivity
https://en.wikipedia.org/wiki/Volumetric_heat_capacity
"""
type Heat <: FieldProblem
formulation :: String
store_fields :: Vector{String}
formulation :: AbstractString
store_fields :: Vector{Symbol}
end
function Heat()
@@ -85,10 +85,19 @@ function assemble!{E<:Heat3DVolumeElements}(assembly::Assembly, problem::Problem
k = element("$field_name thermal conductivity", ip, time)
K += w*k*dN'*dN
end
if haskey(element, "thermal conductivity")
dN = element(ip, time, Val{:Grad})
k = element("thermal conductivity", ip, time)
K += w*k*dN'*dN
end
if haskey(element, "$field_name load")
f = element("$field_name load", ip, time)
fq += w*N'*f
end
if haskey(element, "heat source")
f = element("heat source", ip, time)
fq += w*N'*f
end
end
T = vec(element[field_name](time))
fq -= K*T
@@ -141,12 +150,22 @@ function assemble!{E<:Heat3DSurfaceElements}(assembly::Assembly, problem::Proble
q = element("$field_name flux", ip, time)
fq += w*N'*q
end
if haskey(element, "$field_name heat transfer coefficient")
if haskey(element, "heat flux")
q = element("heat flux", ip, time)
fq += w*N'*q
end
if haskey(element, "$field_name heat transfer coefficient") && haskey(element, "$field_name external temperature")
h = element("$field_name heat transfer coefficient", ip, time)
Tu = element("$field_name external temperature", ip, time)
K += w*h*N'*N
fq += w*N'*h*Tu
end
if haskey(element, "heat transfer coefficient") && haskey(element, "external temperature")
h = element("heat transfer coefficient", ip, time)
Tu = element("external temperature", ip, time)
K += w*h*N'*N
fq += w*N'*h*Tu
end
end
T = vec(element[field_name](time))
fq -= K*T
@@ -178,10 +197,19 @@ function assemble!{E<:Heat2DVolumeElements}(assembly::Assembly, problem::Problem
k = element("$field_name thermal conductivity", ip, time)
K += w*k*dN'*dN
end
if haskey(element, "thermal conductivity")
dN = element(ip, time, Val{:Grad})
k = element("thermal conductivity", ip, time)
K += w*k*dN'*dN
end
if haskey(element, "$field_name load")
f = element("$field_name load", ip, time)
fq += w*N'*f
end
if haskey(element, "heat source")
f = element("heat source", ip, time)
fq += w*N'*f
end
end
T = vec(element[field_name](time))
fq -= K*T
@@ -203,6 +231,22 @@ function assemble!{E<:Heat2DSurfaceElements}(assembly::Assembly, problem::Proble
g = element("$field_name flux", ip, time)
fq += w*N'*g
end
if haskey(element, "heat flux")
g = element("heat flux", ip, time)
fq += w*N'*g
end
if haskey(element, "$field_name heat transfer coefficient") && haskey(element, "$field_name external temperature")
h = element("$field_name heat transfer coefficient", ip, time)
Tu = element("$field_name external temperature", ip, time)
K += w*h*N'*N
fq += w*N'*h*Tu
end
if haskey(element, "heat transfer coefficient") && haskey(element, "external temperature")
h = element("heat transfer coefficient", ip, time)
Tu = element("external temperature", ip, time)
K += w*h*N'*N
fq += w*N'*h*Tu
end
end
T = vec(element[field_name](time))
fq -= K*T
+1 -1
View File
@@ -8,7 +8,7 @@ type Mortar <: BoundaryProblem
dual_basis :: Bool
use_forwarddiff :: Bool
distval :: Float64
store_fields :: Vector{String}
store_fields :: Vector{Symbol}
end
function Mortar()
+6 -6
View File
@@ -4,8 +4,8 @@
abstract AbstractSolver
type Solver{S<:AbstractSolver}
name :: String # some descriptive name for problem
time :: Real # current time
name :: AbstractString # some descriptive name for problem
time :: Float64 # current time
problems :: Vector{Problem}
norms :: Vector{Tuple} # solution norms for convergence studies
ndofs :: Int # number of degrees of freedom in problem
@@ -27,7 +27,7 @@ function push!(solver::Solver, problem)
push!(solver.problems, problem)
end
function getindex(solver::Solver, problem_name::String)
function getindex(solver::Solver, problem_name)
for problem in get_problems(solver)
if problem.name == problem_name
return problem
@@ -485,7 +485,7 @@ function NonlinearSolver(problems...)
end
return solver
end
function NonlinearSolver(name::String, problems::Problem...)
function NonlinearSolver(name::AbstractString, problems::Problem...)
solver = NonlinearSolver(problems...)
solver.name = name
return solver
@@ -550,7 +550,7 @@ function LinearSolver(problems::Problem...)
end
return solver
end
function LinearSolver(name::String, problems::Problem...)
function LinearSolver(name::AbstractString, problems::Problem...)
solver = LinearSolver(problems...)
solver.name = name
return solver
@@ -615,7 +615,7 @@ function Postprocessor(problems::Problem...)
return solver
end
function Postprocessor(name::String, problems::Problem...)
function Postprocessor(name::AbstractString, problems::Problem...)
solver = Postprocessor(problems...)
solver.name = name
return solver
+5 -5
View File
@@ -9,15 +9,15 @@ type Point{P<:AbstractPoint}
id :: Int
weight :: Float64
coords :: Vector{Float64}
fields :: Dict{String, Field}
fields :: Dict{AbstractString, Field}
properties :: P
end
function setindex!{T}(point::Point, val::Pair{Float64, T}, field_name::String)
function setindex!{T}(point::Point, val::Pair{Float64, T}, field_name)
point.fields[field_name] = Field(val)
end
function getindex(point::Point, field_name::String)
function getindex(point::Point, field_name)
return point.fields[field_name]
end
@@ -25,11 +25,11 @@ function getindex(point::Point, idx::Int)
return point.coords[idx]
end
function haskey(point::Point, field_name::String)
function haskey(point::Point, field_name)
return haskey(point.fields, field_name)
end
function call(point::Point, field_name::String, time::Float64=0.0)
function call(point::Point, field_name, time=0.0)
point.fields[field_name](time).data
end
+1 -1
View File
@@ -1,7 +1,7 @@
# This file is a part of JuliaFEM.
# License is MIT: see https://github.com/JuliaFEM/JuliaFEM.jl/blob/master/LICENSE.md
using JuliaFEM.Test
using JuliaFEM.Testing
function run_tests(; verbose=true)
+6 -1
View File
@@ -3,9 +3,12 @@
using JuliaFEM
using JuliaFEM.Preprocess
using JuliaFEM.Testing
#=
using JuliaFEM.API
using JuliaFEM.Interfaces
using JuliaFEM.Test
=#
#= TODO: Fix test
@testset "test basic workflow" begin
@@ -82,6 +85,7 @@ end
end
=#
#= TODO: Fix test
function test_piston_107168()
abaqus_input = open(parse_abaqus, "./geometry/piston/piston_107168_P2.inp")
@@ -91,6 +95,7 @@ function test_piston_107168()
@test length(keys(model.elements)) == 65948
@test length(keys(model.nodes)) == 107168
end
=#
function slow_test_something_that_takes_long_time()
info("This test is SLOW.")
+1 -1
View File
@@ -2,7 +2,7 @@
# License is MIT: see https://github.com/JuliaFEM/JuliaFEM.jl/blob/master/LICENSE.md
using JuliaFEM
using JuliaFEM.Test
using JuliaFEM.Testing
@testset "test static condensation" begin
+1 -1
View File
@@ -2,7 +2,7 @@
# License is MIT: see https://github.com/JuliaFEM/JuliaFEM.jl/blob/master/LICENSE.md
using JuliaFEM
using JuliaFEM.Test
using JuliaFEM.Testing
importall Base
import JuliaFEM: get_basis, get_dbasis
+1 -1
View File
@@ -2,7 +2,7 @@
# License is MIT: see https://github.com/JuliaFEM/JuliaFEM.jl/blob/master/LICENSE.md
using JuliaFEM
using JuliaFEM.Test
using JuliaFEM.Testing
@testset "geometry missing" begin
el = Element(Quad4, [1, 2, 3, 4])
+1 -1
View File
@@ -1,7 +1,7 @@
using JuliaFEM
using JuliaFEM.Preprocess
using JuliaFEM.Postprocess
using JuliaFEM.Test
using JuliaFEM.Testing
@testset "2d curved block with frictionless finite sliding contact using forwarddiff" begin
# FIXME: needs verification of some other fem software
+1 -1
View File
@@ -4,7 +4,7 @@
using JuliaFEM
using JuliaFEM.Preprocess
using JuliaFEM.Postprocess
using JuliaFEM.Test
using JuliaFEM.Testing
import JuliaFEM: get_mesh, get_model
function get_mesh(::Type{Val{Symbol("curved 2d mesh model")}})
+1 -1
View File
@@ -4,7 +4,7 @@
using JuliaFEM
using JuliaFEM.Preprocess
using JuliaFEM.Postprocess
using JuliaFEM.Test
using JuliaFEM.Testing
@testset "3d upper side curved contact" begin
+1 -1
View File
@@ -2,7 +2,7 @@
# License is MIT: see https://github.com/JuliaFEM/JuliaFEM.jl/blob/master/LICENSE.md
using JuliaFEM
using JuliaFEM.Test
using JuliaFEM.Testing
importall Base
import JuliaFEM: get_basis, get_dbasis, get_integration_points
+1 -1
View File
@@ -4,7 +4,7 @@
using JuliaFEM
using JuliaFEM.Preprocess
using JuliaFEM.Postprocess
using JuliaFEM.Test
using JuliaFEM.Testing
# TODO: Fix tests
+1 -1
View File
@@ -4,7 +4,7 @@
using JuliaFEM
using JuliaFEM.Preprocess
using JuliaFEM.Postprocess
using JuliaFEM.Test
using JuliaFEM.Testing
# TODO: Fix tests.
+1 -1
View File
@@ -2,7 +2,7 @@
# License is MIT: see https://github.com/JuliaFEM/JuliaFEM.jl/blob/master/LICENSE.md
using JuliaFEM
using JuliaFEM.Test
using JuliaFEM.Testing
#=
In [36]: C = Matrix([[0], [30], [15]]) # node coordinates
@@ -4,7 +4,7 @@
using JuliaFEM
using JuliaFEM.Preprocess
using JuliaFEM.Postprocess
using JuliaFEM.Test
using JuliaFEM.Testing
using JLD
function JuliaFEM.get_model(::Type{Val{Symbol("test 2d linear elasticity with surface + volume load")}})
@@ -3,7 +3,7 @@
using JuliaFEM
using JuliaFEM.Preprocess
using JuliaFEM.Test
using JuliaFEM.Testing
@testset "2d nonlinear elasticity: test nonhomogeneous boundary conditions and stress calculation" begin
@@ -3,7 +3,7 @@
using JuliaFEM
using JuliaFEM.Preprocess
using JuliaFEM.Test
using JuliaFEM.Testing
@testset "test 2d nonlinear elasticity with surface load" begin
meshfile = "/geometry/2d_block/BLOCK_1elem.med"
@@ -4,7 +4,7 @@
# http://ahojukka5.github.io/posts/finite-element-solution-for-one-element-problem/
using JuliaFEM
using JuliaFEM.Test
using JuliaFEM.Testing
@testset "test 2d linear elasticity local matrices" begin
element = Element(Quad4, [1, 2, 3, 4])
+1 -1
View File
@@ -3,7 +3,7 @@
using JuliaFEM
using JuliaFEM.Preprocess
using JuliaFEM.Test
using JuliaFEM.Testing
@testset "test 2d nonlinear residual" begin
X = Dict{Int64, Vector{Float64}}(
@@ -3,7 +3,7 @@
using JuliaFEM
using JuliaFEM.Preprocess
using JuliaFEM.Test
using JuliaFEM.Testing
@testset "test continuum 3d linear elasticity with surface load" begin
nodes = Dict{Int64, Node}(
@@ -2,7 +2,7 @@
# License is MIT: see https://github.com/JuliaFEM/JuliaFEM.jl/blob/master/LICENSE.md
using JuliaFEM
using JuliaFEM.Test
using JuliaFEM.Testing
@testset "test continuum nonlinear elasticity with surface load" begin
+1 -1
View File
@@ -4,7 +4,7 @@
using JuliaFEM
using JuliaFEM.Preprocess
using JuliaFEM.Postprocess
using JuliaFEM.Test
using JuliaFEM.Testing
function calc_model(mesh_name; with_volume_load=false, debug_print=false)
meshfile = Pkg.dir("JuliaFEM")*"/test/testdata/3d_block.med"
+1 -1
View File
@@ -4,7 +4,7 @@
using JuliaFEM
using JuliaFEM.Preprocess
using JuliaFEM.Postprocess
using JuliaFEM.Test
using JuliaFEM.Testing
#= TODO: Fix test.
@testset "test forwarddiff version + volume load." begin
@@ -3,7 +3,7 @@
using JuliaFEM
using JuliaFEM.Preprocess
using JuliaFEM.Test
using JuliaFEM.Testing
@testset "test tet10 stiffness matrix" begin
el = Element(Tet10, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
@@ -3,7 +3,7 @@
using JuliaFEM
using JuliaFEM.Preprocess
using JuliaFEM.Test
using JuliaFEM.Testing
@testset "test tet4 stiffness matrix" begin
el = Element(Tet4, [1, 2, 3, 4])
+1 -1
View File
@@ -3,7 +3,7 @@
using JuliaFEM
using JuliaFEM.Preprocess
using JuliaFEM.Test
using JuliaFEM.Testing
@testset "test tet4 + volume load" begin
X1 = [2.0, 3.0, 4.0]
+1 -1
View File
@@ -2,7 +2,7 @@
# License is MIT: see https://github.com/JuliaFEM/JuliaFEM.jl/blob/master/LICENSE.md
using JuliaFEM
using JuliaFEM.Test
using JuliaFEM.Testing
#= TODO: Fix test
function test_interpolate()
+4 -1
View File
@@ -1,5 +1,8 @@
# 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.Test
using JuliaFEM.Testing
@testset "inverse isoparametric mapping" begin
el = Element(Quad4, [1, 2, 3, 4])
+1 -1
View File
@@ -2,6 +2,6 @@
# License is MIT: see https://github.com/JuliaFEM/JuliaFEM.jl/blob/master/LICENSE.md
using JuliaFEM
using JuliaFEM.Test
using JuliaFEM.Testing
+1 -1
View File
@@ -3,7 +3,7 @@
using JuliaFEM
using JuliaFEM.Postprocess
using JuliaFEM.Test
using JuliaFEM.Testing
@testset "extrapolate stress from gauss points to nodes" begin
X = Dict{Int, Vector{Float64}}(
+1 -1
View File
@@ -2,7 +2,7 @@
# License is MIT: see https://github.com/JuliaFEM/JuliaFEM.jl/blob/master/LICENSE.md
using JuliaFEM
using JuliaFEM.Test
using JuliaFEM.Testing
@testset "test updating time dependent fields" begin
f = Field(0.0 => 1.0)
+1 -1
View File
@@ -2,7 +2,7 @@
# License is MIT: see https://github.com/JuliaFEM/JuliaFEM.jl/blob/master/LICENSE.md
using JuliaFEM
using JuliaFEM.Test
using JuliaFEM.Testing
@testset "test interpolation of discrete constant time-variant field" begin
f = DCTV(0.0 => 0.0, 1.0 => 1.0)
+1 -1
View File
@@ -2,7 +2,7 @@
# License is MIT: see https://github.com/JuliaFEM/JuliaFEM.jl/blob/master/LICENSE.md
using JuliaFEM
using JuliaFEM.Test
using JuliaFEM.Testing
@testset "find intersection of Seg3 element" begin
el = Element(Seg3, [1, 2, 3])
+1 -1
View File
@@ -2,7 +2,7 @@
# License is MIT: see https://github.com/JuliaFEM/JuliaFEM.jl/blob/master/LICENSE.md
using JuliaFEM
using JuliaFEM.Test
using JuliaFEM.Testing
using JuliaFEM.Preprocess
using JuliaFEM.Postprocess
+2 -1
View File
@@ -1,9 +1,10 @@
# 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.Test
using JuliaFEM.Testing
@testset "3d rod" begin
mesh = aster_read_mesh(Pkg.dir("JuliaFEM")*"/test/testdata/primitives.med", "CYLINDER_20_TET4")
+13 -12
View File
@@ -1,9 +1,10 @@
# 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.Test
using JuliaFEM.Testing
@testset "2d poisson problem with known analytical solution" begin
# from FENiCS tutorial, u(x,y) = 1 + x² + 2y² on [0x1]×[0,1]
@@ -15,8 +16,8 @@ using JuliaFEM.Test
field = Problem(Heat, "unit square, 6x4 triangular mesh", 1)
field.elements = create_elements(mesh, "UNITSQUARE")
field.properties.formulation = "2D"
update!(field, "temperature thermal conductivity", 1.0)
update!(field, "temperature load", -6.0)
update!(field, "thermal conductivity", 1.0)
update!(field, "heat source", -6.0)
bc = Problem(Dirichlet, "u₀(x,y) = 1 + x² + 2y²", 1, "temperature")
#bc.properties.order = 2
@@ -35,18 +36,18 @@ using JuliaFEM.Test
T_fem = Float64[]
T_acc = Float64[]
for (nid, X) in field("geometry")
# info("$nid -> $X")
push!(T_fem, field("temperature", X)[1])
push!(T_acc, 1.0 + X[1]^2 + 2*X[2]^2)
end
for element in bc.elements
for (X, T_fem) in zip(element("geometry", 0.0), element("temperature", 0.0))
x, y = X
T_acc = 1.0 + x^2 + 2*y^2
# info("(x,y) = ($x,$y), T_acc = $T_acc, T_fem = $T_fem")
end
end
@test maximum(abs(T_fem-T_acc)) < 1.0e-12
# gradient of field is
gradT(X) = [2*X[1] 4*X[2]]
X = [0.5, 0.5]
gradT1 = gradT(X)
gradT2 = field("temperature", X, solver.time, Val{:Grad})
info("gradT1 = $gradT1, gradT2 = $gradT2")
# [1.1666666666666625 1.5000000000000018] quite big difference ..?
@test isapprox(gradT1, gradT2; rtol=25.0e-2)
end
+1 -1
View File
@@ -2,7 +2,7 @@
# License is MIT: see https://github.com/JuliaFEM/JuliaFEM.jl/blob/master/LICENSE.md
using JuliaFEM
using JuliaFEM.Test
using JuliaFEM.Testing
@testset "test integration point" begin
ip = IP(1, 1.0, sqrt(1.0/3.0)*[-1.0, -1.0])
+1 -1
View File
@@ -3,7 +3,7 @@
module InterfaceTests
using JuliaFEM.Test
using JuliaFEM.Testing
function test_foo()
@test 1+2 == 3
+8 -3
View File
@@ -2,12 +2,15 @@
# License is MIT: see https://github.com/JuliaFEM/JuliaFEM.jl/blob/master/LICENSE.md
using JuliaFEM
using JuliaFEM.Test
using JuliaFEM.Testing
ALL_ELEMENTS = [
Seg2, Seg3,
Tri3, Tri6, Quad4, Quad8, Quad9,
Tet4, Tet10, Hex8, Hex20, Hex27
Tri3, Tri6, Tri7,
Quad4, Quad8, Quad9,
Tet4, Tet10,
Wedge6,
Hex8, Hex20, Hex27
]
@testset "Evaluating basis" begin
@@ -39,11 +42,13 @@ end
@test isapprox(get_volume(Seg3), 2.0)
@test isapprox(get_volume(Tri3), 0.5)
@test isapprox(get_volume(Tri6), 0.5)
@test isapprox(get_volume(Tri7), 0.5)
@test isapprox(get_volume(Quad4), 2.0^2)
@test isapprox(get_volume(Quad8), 2.0^2)
@test isapprox(get_volume(Quad9), 2.0^2)
@test isapprox(get_volume(Tet4), 1/6)
@test isapprox(get_volume(Tet10), 1/6)
@test isapprox(get_volume(Wedge6), 1.0)
@test isapprox(get_volume(Hex8), 2.0^3)
@test isapprox(get_volume(Hex20), 2.0^3)
@test isapprox(get_volume(Hex27), 2.0^3)
+1 -1
View File
@@ -2,7 +2,7 @@
# License is MIT: see https://github.com/JuliaFEM/JuliaFEM.jl/blob/master/LICENSE.md
using JuliaFEM
using JuliaFEM.Test
using JuliaFEM.Testing
@testset "test eigenvalues for single tet4 element" begin
X = Dict{Int, Vector{Float64}}(
+1 -1
View File
@@ -2,7 +2,7 @@
# License is MIT: see https://github.com/JuliaFEM/JuliaFEM.jl/blob/master/LICENSE.md
using JuliaFEM
using JuliaFEM.Test
using JuliaFEM.Testing
function test_auxiliary_plane_transforms()
nodes = Vector{Float64}[
+1 -1
View File
@@ -2,7 +2,7 @@
# License is MIT: see https://github.com/JuliaFEM/JuliaFEM.jl/blob/master/LICENSE.md
using JuliaFEM
using JuliaFEM.Test
using JuliaFEM.Testing
function get_test_model()
+1 -1
View File
@@ -2,7 +2,7 @@
# License is MIT: see https://github.com/JuliaFEM/JuliaFEM.jl/blob/master/LICENSE.md
using JuliaFEM
using JuliaFEM.Test
using JuliaFEM.Testing
function get_test_2d_model()
X = Dict{Int64, Vector{Float64}}(
+1 -1
View File
@@ -2,7 +2,7 @@
# License is MIT: see https://github.com/JuliaFEM/JuliaFEM.jl/blob/master/LICENSE.md
using JuliaFEM
using JuliaFEM.Test
using JuliaFEM.Testing
function get_test_2d_model()
X = Dict{Int64, Vector{Float64}}(
+7 -7
View File
@@ -3,7 +3,7 @@
using JuliaFEM
using JuliaFEM.Preprocess
using JuliaFEM.Test
using JuliaFEM.Testing
function JuliaFEM.get_mesh(::Type{Val{Symbol("two elements 1.0x0.5 with 0.1 gap in y direction")}})
mesh = Mesh()
@@ -21,12 +21,12 @@ function JuliaFEM.get_mesh(::Type{Val{Symbol("two elements 1.0x0.5 with 0.1 gap
add_element!(mesh, 4, :Seg2, [7, 8])
add_element!(mesh, 5, :Seg2, [4, 3])
add_element!(mesh, 6, :Seg2, [6, 5])
add_element_to_element_set!(mesh, "LOWER", 1)
add_element_to_element_set!(mesh, "UPPER", 2)
add_element_to_element_set!(mesh, "LOWER_BOTTOM", 3)
add_element_to_element_set!(mesh, "UPPER_TOP", 4)
add_element_to_element_set!(mesh, "LOWER_TOP", 5)
add_element_to_element_set!(mesh, "UPPER_BOTTOM", 6)
add_element_to_element_set!(mesh, :LOWER, 1)
add_element_to_element_set!(mesh, :UPPER, 2)
add_element_to_element_set!(mesh, :LOWER_BOTTOM, 3)
add_element_to_element_set!(mesh, :UPPER_TOP, 4)
add_element_to_element_set!(mesh, :LOWER_TOP, 5)
add_element_to_element_set!(mesh, :UPPER_BOTTOM, 6)
return mesh
end
+1 -1
View File
@@ -4,7 +4,7 @@
using JuliaFEM
using JuliaFEM.Preprocess
using JuliaFEM.Postprocess
using JuliaFEM.Test
using JuliaFEM.Testing
function get_test_model()
X = Dict{Int64, Vector{Float64}}(
+1 -1
View File
@@ -4,7 +4,7 @@
using JuliaFEM
using JuliaFEM.Preprocess
using JuliaFEM.Postprocess
using JuliaFEM.Test
using JuliaFEM.Testing
function JuliaFEM.get_mesh(::Type{Val{Symbol("curved 2d block splitted to upper and lower")}})
meshfile = Pkg.dir("JuliaFEM") * "/test/testdata/block_2d_curved.med"
+1 -1
View File
@@ -1,7 +1,7 @@
# This file is a part of JuliaFEM.
# License is MIT: see https://github.com/JuliaFEM/JuliaFEM.jl/blob/master/LICENSE.md
using JuliaFEM.Test
using JuliaFEM.Testing
#= TODO: Fix test.
@testset "calculate mortar matrices and weighted gap vector for 2d model" begin
+1 -1
View File
@@ -4,7 +4,7 @@
using JuliaFEM
using JuliaFEM.Preprocess
using JuliaFEM.Postprocess
using JuliaFEM.Test
using JuliaFEM.Testing
@testset "test that interface transfers constant field without error" begin
meshfile = Pkg.dir("JuliaFEM") * "/test/testdata/block_3d.med"
+1 -1
View File
@@ -2,7 +2,7 @@
# License is MIT: see https://github.com/JuliaFEM/JuliaFEM.jl/blob/master/LICENSE.md
using JuliaFEM
using JuliaFEM.Test
using JuliaFEM.Testing
@testset "polygon clip case 1" begin
S = Vector[
+1 -1
View File
@@ -2,7 +2,7 @@
# License is MIT: see https://github.com/JuliaFEM/JuliaFEM.jl/blob/master/LICENSE.md
using JuliaFEM
using JuliaFEM.Test
using JuliaFEM.Testing
function get_testproblems(u, la)
nodes = Dict{Int64, Node}(
+1 -2
View File
@@ -1,9 +1,8 @@
# 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.Test
using JuliaFEM.Testing
function JuliaFEM.get_model(::Type{Val{Symbol("1x1 plane stress quad4 block")}})
+1 -1
View File
@@ -1,7 +1,7 @@
# This file is a part of JuliaFEM.
# License is MIT: see https://github.com/JuliaFEM/JuliaFEM.jl/blob/master/LICENSE.md
using JuliaFEM.Test
using JuliaFEM.Testing
#=
@testset "find dofs given a set of nodes" begin
+1 -1
View File
@@ -1,5 +1,5 @@
using JuliaFEM
using JuliaFEM.Test
using JuliaFEM.Testing
@testset "get nodal values" begin
el1 = Element(Seg2, [1, 2])
+1 -1
View File
@@ -2,7 +2,7 @@
# License is MIT: see https://github.com/JuliaFEM/JuliaFEM.jl/blob/master/LICENSE.md
using JuliaFEM
using JuliaFEM.Test
using JuliaFEM.Testing
abstract HeatProblem <: AbstractProblem
+1 -65
View File
@@ -4,7 +4,7 @@
using JuliaFEM
using JuliaFEM.Preprocess
using JuliaFEM.Postprocess
using JuliaFEM.Test
using JuliaFEM.Testing
@testset "renumber element nodes" begin
mesh = Mesh()
@@ -19,67 +19,3 @@ using JuliaFEM.Test
@test mesh.elements[1] == [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
end
function get_volume(element::Element, time=0.0)
V = 0.0
for ip in get_integration_points(element)
V += ip.weight*element(ip, time, Val{:detJ})
end
return V
end
function get_volume(elements::Vector{Element}, time=0.0)
return sum([get_volume(element, time) for element in elements])
end
#=
@testset "Hex8 element connectivity order" begin
fn = Pkg.dir("JuliaFEM") * "/test/testdata/rod_short.med"
mesh = aster_read_mesh(fn, "SHORT_ROD_RECTANGLE_HE8_1ELEM")
# 1. check volume of element
rod = create_elements(mesh, "ROD")
V = get_volume(rod)
V_expected = 0.01^2*0.2
info("Volume of rod = $V, expected = $V_expected")
@test isapprox(V, V_expected)
# 2. put some field value and calculate flux in gauss points
T = Dict{Int64, Float64}(
1 => 100.0, 2 => 100.0, 3 => 100.0, 4 => 100.0,
5 => 200.0, 6 => 300.0, 7 => 400.0, 8 => 500.0)
update!(rod, "temperature", T)
# it has been verified using code aster that flux in integration
# points is
FLUX_ELGA = Dict{Int, Vector{Float64}}(
1 => [-4.08493649053890E+04, -2.11324865405187E+05, 1.05662432702594E+05],
2 => [-4.08493649053890E+04, -7.88675134594813E+05, 3.94337567297406E+05],
3 => [-6.97168783648703E+04, -2.11324865405187E+05, 1.05662432702594E+05],
4 => [-6.97168783648703E+04, -7.88675134594813E+05, 3.94337567297406E+05],
5 => [-5.52831216351297E+04, -2.11324865405187E+05, 1.05662432702594E+05],
6 => [-5.52831216351297E+04, -7.88675134594813E+05, 3.94337567297406E+05],
7 => [-8.41506350946110E+04, -2.11324865405187E+05, 1.05662432702594E+05],
8 => [-8.41506350946110E+04, -7.88675134594813E+05, 3.94337567297406E+05])
# flux is q̄(ξ) = -k∇T
element = first(rod)
k = -50.0
flux(xi, time) = -k*vec(element("temperature", xi, time, Val{:Grad}))
weights = ones(8)
# code aster integration points (FPG8)
a = -1.0/sqrt(3.0)
points = Vector{Float64}[
[-a, -a, -a],
[-a, -a, a],
[-a, a, -a],
[-a, a, a],
[ a, -a, -a],
[ a, -a, a],
[ a, a, -a],
[ a, a, a]]
for i=1:8
q1 = flux(points[i], 0.0)
q2 = FLUX_ELGA[i]
rtol = norm(q1-q2)/max(norm(q1),norm(q2))*100.0
@printf "ip %i flux, JF: (% e,% e,% e), CA: (% e,% e,% e), rtol: %10.6f %%\n" i q1... q2... rtol
@test rtol < 0.05
end
end
=#
@@ -3,7 +3,7 @@
using JuliaFEM
using JuliaFEM.Preprocess
using JuliaFEM.Test
using JuliaFEM.Testing
@testset "read inp file" begin
model = open(parse_abaqus, Pkg.dir("JuliaFEM")*"/geometry/3d_beam/palkki.inp")
@@ -34,45 +34,20 @@ end
@test model["elsets"]["BEAM"] == [1, 2]
end
@testset "test unknown handler warning message" begin
fn = tempname()
fid = open(fn, "w")
testdata = """*ELEMENT2, TYPE=C3D10, ELSET=Body1
1, 243, 240, 191, 117, 245, 242, 244,
1, 2, 196
"""
write(fid, testdata)
close(fid)
model = open(parse_abaqus, fn)
# empty model expected, parser doesn't know what to do with unknown section
@test length(model) == 0
@testset "parse nodes from abaqus .inp file to Mesh" begin
fn = Pkg.dir("JuliaFEM") * "/test/testdata/cube_tet4.inp"
mesh = abaqus_read_mesh(fn)
info(mesh.surfaces)
@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.surfaces, :LOAD)
@test length(mesh.surfaces[:LOAD]) == 2
@test mesh.surfaces[:LOAD][1] == (16, :S1)
@test mesh.surface_types[:LOAD] == :ELEMENT
end
#= TODO: fix test
@testset "test that reader throws error when dimension information of element is missing" begin
# *ELEMENT, TYPE=neverseenbefore, ELSET=Body1
data = """
1, 243, 240, 191, 117, 245, 242, 244,
1, 2, 196
"""
model = Dict()
header = Dict("section"=>"ELEMENT", "options" => Dict("TYPE" => "neverseenbefore", "ELSET"=>"Body1"))
@test_throws Exception parse_element_section(model, header, data)
end
=#
#= TODO: fix test
@testset "test read surface set section" begin
data = """*SURFACE, TYPE=ELEMENT, NAME=LOAD
31429,S1
31481,S3
"""
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, :SURFACE, 1, 3, Val{:SURFACE})
@test model["surfaces"]["LOAD"] == [(31429,1), (31481,3)]
end
=#
+11 -51
View File
@@ -3,7 +3,7 @@
using JuliaFEM
using JuliaFEM.Preprocess
using JuliaFEM.Test
using JuliaFEM.Testing
@testset "read ascii mesh" begin
mesh = """
@@ -64,48 +64,6 @@ end
@test length(nodes) == 8
end
@testset "test combining meshes" begin
mesh1 = Dict{String, Any}(
"nodes" => Dict{Int64, Vector{Float64}}(
1 => [1.0, 2.0],
2 => [2.0, 3.0]
),
"connectivity" => Dict{Int64, Tuple{Symbol, Symbol, Vector{Int64}}}(
1 => (:SE2, :GRP1, [1, 2])
),
)
mesh2 = Dict{String, Any}(
"nodes" => Dict{Int64, Vector{Float64}}(
1 => [3.0, 4.0],
2 => [4.0, 5.0]
),
"connectivity" => Dict{Int64, Tuple{Symbol, Symbol, Vector{Int64}}}(
1 => (:SE2, :GRP1, [1, 2])
),
)
aster_renumber_nodes!(mesh1, mesh2)
@test length(mesh2["nodes"]) == 2
@test 3 in keys(mesh2["nodes"])
@test 4 in keys(mesh2["nodes"])
@test mesh2["connectivity"][1] == (:SE2, :GRP1, [3, 4])
aster_renumber_elements!(mesh1, mesh2)
@test length(mesh2["connectivity"]) == 1
@test mesh2["connectivity"][2] == (:SE2, :GRP1, [3, 4])
mesh = aster_combine_meshes(mesh1, mesh2)
@test length(mesh["nodes"]) == 4
@test mesh["nodes"][1] == [1.0, 2.0]
@test mesh["nodes"][2] == [2.0, 3.0]
@test mesh["nodes"][3] == [3.0, 4.0]
@test mesh["nodes"][4] == [4.0, 5.0]
@test mesh["connectivity"][1] == (:SE2, :GRP1, [1, 2])
@test mesh["connectivity"][2] == (:SE2, :GRP1, [3, 4])
end
function JuliaFEM.get_mesh(::Type{Val{Symbol("block_2d_1elem_quad4")}})
fn = Pkg.dir("JuliaFEM") * "/test/testdata/block_2d_1elem_quad4.med"
mesh = aster_read_mesh(fn)
@@ -114,6 +72,7 @@ end
@testset "test reading aster .med file" begin
mesh = get_mesh("block_2d_1elem_quad4")
#=
info("nodes")
for (k, v) in mesh.nodes
info("$k => $v")
@@ -130,15 +89,16 @@ end
for (k, v) in mesh.element_sets
info("$k => $v")
end
=#
@test length(mesh.element_sets) == 5
@test length(mesh.node_sets) == 4
@test length(mesh.elements) == 5
@test length(mesh.nodes) == 4
for elset in ["BLOCK", "TOP", "BOTTOM", "LEFT", "RIGHT"]
for elset in [:BLOCK, :TOP, :BOTTOM, :LEFT, :RIGHT]
@test haskey(mesh.element_sets, elset)
@test length(mesh.element_sets[elset]) == 1
end
for nset in ["TOP_LEFT", "TOP_RIGHT", "BOTTOM_LEFT", "BOTTOM_RIGHT"]
for nset in [:TOP_LEFT, :TOP_RIGHT, :BOTTOM_LEFT, :BOTTOM_RIGHT]
@test haskey(mesh.node_sets, nset)
@test length(mesh.node_sets[nset]) == 1
end
@@ -146,15 +106,15 @@ end
@testset "test filter by element set" begin
mesh = get_mesh("block_2d_1elem_quad4")
mesh2 = filter_by_element_set(mesh, "BLOCK")
@test haskey(mesh2.element_sets, "BLOCK")
mesh2 = filter_by_element_set(mesh, :BLOCK)
@test haskey(mesh2.element_sets, :BLOCK)
@test length(mesh2.elements) == 1
end
function calculate_volume(mesh_name::String, eltype::Symbol)
function calculate_volume(mesh_name, eltype)
fn = Pkg.dir("JuliaFEM") * "/test/testdata/primitives.med"
mesh = aster_read_mesh(fn, mesh_name)
elements = create_elements(mesh, eltype)
elements = create_elements(mesh; element_type=eltype)
V = 0.0
time = 0.0
for element in elements
@@ -171,7 +131,7 @@ end
@testset "calculate volume for 1 element models" begin
@test isapprox(calculate_volume("TRIANGLE_TRI3_1", :Tri3), 1/2)
@test isapprox(calculate_volume("TRIANGLE_TRI6_1", :Tri6), 1/2)
# @test isapprox(calculate_volume("TRIANGLE_TRI7_1", :Tri7), 1/2)
@test isapprox(calculate_volume("TRIANGLE_TRI7_1", :Tri7), 1/2)
@test isapprox(calculate_volume("SQUARE_QUAD4_1", :Quad4), 2^2)
@test isapprox(calculate_volume("SQUARE_QUAD8_1", :Quad8), 2^2)
@test isapprox(calculate_volume("SQUARE_QUAD9_1", :Quad9), 2^2)
@@ -181,7 +141,7 @@ end
@test isapprox(calculate_volume("CUBE_HEX8_1", :Hex8), 2^3)
@test isapprox(calculate_volume("CUBE_HEX20_1", :Hex20), 2^3)
@test isapprox(calculate_volume("CUBE_HEX27_1", :Hex27), 2^3)
# @test isapprox(calculate_volume("WEDGE_WEDGE6_1", :Wedge6, 1/2))
@test isapprox(calculate_volume("WEDGE_WEDGE6_1", :Wedge6), 1)
# @test isapprox(calculate_volume("WEDGE_WEDGE15_1", :Wedge15, 1/2))
# @test isapprox(calculate_volume("PYRAMID_PYRAMID5_1", :Pyramid5, ?))
# @test isapprox(calculate_volume("PYRAMID_PYRAMID13_1", :Pyramid13, ?))
+3 -2
View File
@@ -2,7 +2,7 @@
# License is MIT: see https://github.com/JuliaFEM/JuliaFEM.jl/blob/master/LICENSE.md
using JuliaFEM
using JuliaFEM.Test
using JuliaFEM.Testing
@testset "test initialize field problem" begin
el = Element(Seg2, [1, 2])
@@ -11,8 +11,9 @@ using JuliaFEM.Test
initialize!(pr)
@test haskey(el, "temperature")
# one timestep in field "temperature"
@test length(el("temperature")) == 1
@test length(el["temperature"]) == 1
# this way we access to field at default time t=0.0, it's different than ^!
@test length(el("temperature")) == 2
# length of single increment
@test length(el("temperature", 0.0)) == 2
@test length(last(el, "temperature").data) == 2
+1 -1
View File
@@ -2,7 +2,7 @@
# License is MIT: see https://github.com/JuliaFEM/JuliaFEM.jl/blob/master/LICENSE.md
using JuliaFEM
using JuliaFEM.Test
using JuliaFEM.Testing
@testset "test projection" begin
C = [
+1 -1
View File
@@ -2,7 +2,7 @@
# License is MIT: see https://github.com/JuliaFEM/JuliaFEM.jl/blob/master/LICENSE.md
using JuliaFEM
using JuliaFEM.Test
using JuliaFEM.Testing
function test_linearsolver()
el1 = Quad4([1, 2, 3, 4])
+40
View File
@@ -0,0 +1,40 @@
# 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.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 == :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.content) == 2
bc = step.content[1]
@test bc[1] == [:SYM12, 3]
@test bc[2] == [:SYM23, 1]
@test bc[3] == [:SYM13, 2]
load = step.content[2]
@test load[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)
model()
end
=#
+1 -1
View File
@@ -2,7 +2,7 @@
# License is MIT: see https://github.com/JuliaFEM/JuliaFEM.jl/blob/master/LICENSE.md
using JuliaFEM
using JuliaFEM.Test
using JuliaFEM.Testing
#= TODO: Fix test
+1 -1
View File
@@ -2,7 +2,7 @@
# License is MIT: see https://github.com/JuliaFEM/JuliaFEM.jl/blob/master/LICENSE.md
using JuliaFEM
using JuliaFEM.Test
using JuliaFEM.Testing
abstract PlaneStressElasticityProblem <: AbstractProblem
+4 -3
View File
@@ -1,7 +1,8 @@
#using PyPlot
using JuliaFEM.Test
using JuliaFEM.MaterialModels: stiffnessTensor, calculate_stress, State
using JuliaFEM.MaterialModels: stiffnessTensorPlaneStress
using JuliaFEM.Testing
#using JuliaFEM.MaterialModels: stiffnessTensor, calculate_stress, State
#using JuliaFEM.MaterialModels: stiffnessTensorPlaneStress
function test_von_mises_3D_basic()
+1 -1
View File
@@ -3,7 +3,7 @@
using JuliaFEM
using JuliaFEM.Postprocess
using JuliaFEM.Test
using JuliaFEM.Testing
testdata = """\
<?xml version="1.0" encoding="utf-8"?>
+54
View File
@@ -0,0 +1,54 @@
*NODE, NSET=NALL
1, 4.07417, 3.51532, 4.43035
2, 6.24583, 4.69753, 6.40067
3, 10.00000, 10.00000, 0.00000
4, 10.00000, 0.00000, 0.00000
5, 0.00000, 0.00000, 0.00000
6, 0.00000, 10.00000, 0.00000
7, 0.00000, 10.00000, 10.00000
8, 0.00000, 0.00000, 10.00000
9, 10.00000, 10.00000, 10.00000
10, 10.00000, 0.00000, 10.00000
*ELEMENT, TYPE=C3D4, ELSET=CUBE
1, 8, 10, 1, 2
2, 4, 1, 10, 2
3, 3, 9, 7, 2
4, 3, 5, 4, 1
5, 8, 7, 2, 1
6, 5, 6, 8, 1
7, 7, 6, 1, 8
8, 7, 9, 8, 2
9, 5, 8, 10, 1
10, 3, 6, 5, 1
11, 4, 10, 9, 2
12, 1, 7, 2, 3
13, 3, 4, 9, 2
14, 3, 1, 4, 2
15, 4, 5, 10, 1
16, 8, 9, 10, 2
17, 3, 6, 1, 7
*SOLID SECTION, ELSET=CUBE, MATERIAL=MAT
*MATERIAL, NAME=MAT
*ELASTIC
2.08000e+005, 3.00000e-001
*NSET, NSET=SYM12
5, 6, 3, 4,
*NSET, NSET=SYM23
5, 6, 7, 8,
*NSET, NSET=SYM13
5, 10, 8, 4,
*SURFACE, TYPE=ELEMENT, NAME=LOAD
16, S1
8, S1
*STEP
*STATIC
*BOUNDARY
SYM12, 3
SYM23, 1
SYM13, 2
*DSLOAD
LOAD, P, 1.00000
*NODE FILE
COORD
U
*END STEP
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.