Skip to content

Commit

Permalink
Fix coverage (#1)
Browse files Browse the repository at this point in the history
`FEMBase.jl` is now 100 % tested.
  • Loading branch information
ahojukka5 committed Nov 30, 2017
1 parent 110acde commit 965cb88
Show file tree
Hide file tree
Showing 16 changed files with 1,046 additions and 24 deletions.
1 change: 1 addition & 0 deletions src/FEMBase.jl
Expand Up @@ -36,5 +36,6 @@ export Poi1, Seg2, Seg3, Tri3, Tri6, Tri7, Quad4, Quad8, Quad9,
export update!, add_elements!, add!, get_gdofs, group_by_element_type,
get_unknown_field_name, get_unknown_field_dimension,
get_integration_points, initialize!, assemble!
export DCTI, DVTI, DCTV, DVTV, CCTI, CVTI, CCTV, CVTV

end
5 changes: 5 additions & 0 deletions src/assembly.jl
Expand Up @@ -44,6 +44,11 @@ function assemble!(problem::Problem, time=0.0; auto_initialize=true)
return true
end

function assemble!{P}(assembly::Assembly, problem::Problem{P}, element::Element, time)
warn("One must define assemble! function for problem of type $P. Not doing anything.")
return nothing
end

function assemble!(assembly::Assembly, problem::Problem, elements::Vector{Element}, time)
warn("assemble!() this is default assemble operation, decreased performance can be expected without preallocation of memory!")
for element in elements
Expand Down
15 changes: 0 additions & 15 deletions src/elements.jl
Expand Up @@ -371,21 +371,6 @@ function get_integration_points{E}(element::Element{E}, change_order::Int)
end
end

""" Return dual basis transformation matrix Ae. """
function get_dualbasis(element::Element, time::Float64, order=1)
nnodes = length(element)
De = zeros(nnodes, nnodes)
Me = zeros(nnodes, nnodes)
for ip in get_integration_points(element, order)
detJ = element(ip, time, Val{:detJ})
w = ip.weight*detJ
N = element(ip, time)
De += w*diagm(vec(N))
Me += w*N'*N
end
return De, Me, De*inv(Me)
end

""" Find inverse isoparametric mapping of element. """
function get_local_coordinates(element::Element, X::Vector, time::Float64; max_iterations=10, tolerance=1.0e-6)
haskey(element, "geometry") || error("element geometry not defined, cannot calculate inverse isoparametric mapping")
Expand Down
13 changes: 5 additions & 8 deletions src/problems.jl
Expand Up @@ -150,10 +150,6 @@ function get_unknown_field_name{P<:BoundaryProblem}(::Type{P})
return "lambda"
end

function get_assembly(problem)
return problem.assembly
end

# one-liner helpers to identify problem types

is_field_problem(problem) = false
Expand Down Expand Up @@ -395,6 +391,11 @@ function get_unknown_field_dimension(problem::Problem)
return problem.dimension
end

function get_unknown_field_name{P<:AbstractProblem}(::Type{P})
warn("The name of unknown field (e.g. displacement, temperature, ...) of the problem type must be given by defining function `get_unknown_field_name`")
return "N/A"
end

""" Return the name of the unknown field of this problem. """
function get_unknown_field_name{P}(problem::Problem{P})
return get_unknown_field_name(P)
Expand All @@ -409,10 +410,6 @@ function push!(problem::Problem, elements...)
push!(problem.elements, elements...)
end

function push!(problem::Problem, elements::Vector)
push!(problem.elements, elements...)
end

function push!(problem::Problem, elements_::Vector...)
for elements in elements_
push!(problem.elements, elements...)
Expand Down
2 changes: 1 addition & 1 deletion src/types.jl
Expand Up @@ -72,5 +72,5 @@ end

function IP(id, weight, coords::Vector)
warn("Consider giving coords as Tuple.")
return IP(id, weight, [c for c in coords], Dict(), IntegrationPoint())
return IP(id, weight, tuple(coords...), Dict(), IntegrationPoint())
end
9 changes: 9 additions & 0 deletions test/runtests.jl
Expand Up @@ -6,6 +6,15 @@ using TimerOutputs
const to = TimerOutput()

test_files = String[]
push!(test_files, "test_assembly.jl")
push!(test_files, "test_add_elements.jl")
push!(test_files, "test_common_failures.jl")
push!(test_files, "test_elements.jl")
push!(test_files, "test_fields.jl")
push!(test_files, "test_integrate.jl")
push!(test_files, "test_problems.jl")
push!(test_files, "test_sparse.jl")
push!(test_files, "test_types.jl")

@testset "FEMBase.jl" begin
for fn in test_files
Expand Down
16 changes: 16 additions & 0 deletions test/test_add_elements.jl
@@ -0,0 +1,16 @@
# This file is a part of JuliaFEM.
# License is MIT: see https://github.com/JuliaFEM/FEMBase.jl/blob/master/LICENSE

using FEMBase
using Base.Test

type Dummy <: FEMBase.FieldProblem
end

@testset "add elements to problem" begin
problem = Problem(Dummy, "test", 2)
element = Element(Quad4, [1, 2, 3, 4])
elements = [element]
add_elements!(problem, elements)
@test problem.elements[1] == element
end
111 changes: 111 additions & 0 deletions test/test_assembly.jl
@@ -0,0 +1,111 @@
# This file is a part of JuliaFEM.
# License is MIT: see https://github.com/JuliaFEM/FEMBase.jl/blob/master/LICENSE

using FEMBase
using FEMBase: assemble_mass_matrix!
using Base.Test

type Dummy <: FieldProblem end

@testset "test tet4 mass matrix" begin
X = Dict(
1 => [2.0, 3.0, 4.0],
2 => [6.0, 3.0, 2.0],
3 => [2.0, 5.0, 1.0],
4 => [4.0, 3.0, 6.0])

element = Element(Tet4, [1, 2, 3, 4])
update!(element, "geometry", X)
update!(element, "density", 5.0)

p = Problem(Dummy, "test", 1)
add_elements!(p, [element])
assemble_mass_matrix!(p, 0.0)
M = full(p.assembly.M)

M_expected = [
2 1 1 1
1 2 1 1
1 1 2 1
1 1 1 2
]
@test isapprox(M, M_expected)
assemble_mass_matrix!(p, 0.0)
M = full(p.assembly.M)
@test isapprox(M, M_expected)
end

@testset "test tet10 mass matrix" begin
X = Dict(
1 => [2.0, 3.0, 4.0],
2 => [6.0, 3.0, 2.0],
3 => [2.0, 5.0, 1.0],
4 => [4.0, 3.0, 6.0])
X[5] = 1/2*(X[1] + X[2])
X[6] = 1/2*(X[2] + X[3])
X[7] = 1/2*(X[3] + X[1])
X[8] = 1/2*(X[1] + X[4])
X[9] = 1/2*(X[2] + X[4])
X[10] = 1/2*(X[3] + X[4])

element = Element(Tet10, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
update!(element, "geometry", X)
update!(element, "density", 105.0)

p = Problem(Dummy, "test", 1)
add_elements!(p, [element])
assemble_mass_matrix!(p, 0.0)
M = full(p.assembly.M)

M_expected = [
6 1 1 1 -4 -6 -4 -4 -6 -6
1 6 1 1 -4 -4 -6 -6 -4 -6
1 1 6 1 -6 -4 -4 -6 -6 -4
1 1 1 6 -6 -6 -6 -4 -4 -4
-4 -4 -6 -6 32 16 16 16 16 8
-6 -4 -4 -6 16 32 16 8 16 16
-4 -6 -4 -6 16 16 32 16 8 16
-4 -6 -6 -4 16 8 16 32 16 16
-6 -4 -6 -4 16 16 8 16 32 16
-6 -6 -4 -4 8 16 16 16 16 32]

@test isapprox(M, M_expected)

X[5] += 0.1
update!(element, "geometry", X)
empty!(p.assembly.M)
assemble_mass_matrix!(p, 0.0)
M = full(p.assembly.M)
end

@testset "add, empty and compare assembly" begin
A = Assembly()
B = Assembly()
@test isempty(A)
add!(A.K, [1,2,3,4], [1,2,3,4], [1.0 2.0; 3.0 4.0])
add!(B.K, [1,2,3,4], [1,2,3,4], [1.0 2.0; 3.0 4.0])
@test isapprox(A, B)
@test !isempty(A)
empty!(A)
@test isempty(A)
end

function FEMBase.assemble_prehook!(problem::Problem{Dummy}, time::Float64)
add!(problem.assembly.K, [1, 2], [1, 2], [1.0 -1.0; -1.0 1.0])
end

function FEMBase.assemble_posthook!(problem::Problem{Dummy}, time::Float64)
add!(problem.assembly.K, [2, 3], [2, 3], [1.0 -1.0; -1.0 1.0])
end

@testset "pre and posthooks, warnings" begin
p = Problem(Dummy, "test", 1)
assemble!(p, 0.0)
k = [1.0 -1.0; -1.0 1.0]
K_expected = zeros(3,3)
K_expected[1:2,1:2] += k
K_expected[2:3,2:3] += k
@test isapprox(full(p.assembly.K), K_expected)
assemble!(p, 0.0)
@test isapprox(full(p.assembly.K), 2.0*K_expected)
end
15 changes: 15 additions & 0 deletions test/test_common_failures.jl
@@ -0,0 +1,15 @@
# This file is a part of JuliaFEM.
# License is MIT: see https://github.com/JuliaFEM/FEMBase.jl/blob/master/LICENSE

using FEMBase
using Base.Test

type Dummy <: FieldProblem end

@testset "no unknown field name or assemble!-function defined" begin
el = Element(Quad4, [1, 2, 3, 4])
pr = Problem(Dummy, "problem", 2)
add_elements!(pr, [el])
assemble!(pr)
@test true
end

0 comments on commit 965cb88

Please sign in to comment.