code refactoring

This commit is contained in:
Jukka Aho
2016-06-27 16:11:33 +03:00
parent 90f7c581c5
commit 6993828927
20 changed files with 1627 additions and 362 deletions
+32
View File
@@ -31,6 +31,7 @@ Matrix([
p1 = Problem(Dirichlet, "test problem 1", 1, "temperature")
p1.properties.dual_basis = false
p2 = Problem(Dirichlet, "test problem 2", 1, "temperature")
p2.properties.dual_basis = true
assemble!(p1, element)
assemble!(p2, element)
C1 = full(p1.assembly.C1)
@@ -48,6 +49,7 @@ Matrix([
p1 = Problem(Dirichlet, "quadratic 1", 1, "temperature")
p1.properties.dual_basis = false
p2 = Problem(Dirichlet, "quadratic 1", 1, "temperature")
p2.properties.dual_basis = true
assemble!(p1, element)
assemble!(p2, element)
C1 = full(p1.assembly.C1)
@@ -112,3 +114,33 @@ end
end
=#
@testset "test analytical boundary condition" begin
X = Dict{Int64, Vector{Float64}}(
1 => [0.0, 0.0],
2 => [1.0, 0.0])
element = Element(Seg2, [1, 2])
update!(element, "geometry", X)
update!(element, "displacement 1", 0.0)
f(xi, time) = begin
info("function call at xi = $xi, time = $time")
X = element("geometry", xi, time)
info("geometry at xi, X = $X")
val = X[1]*time
info("result for field at xi = $val")
return val
end
update!(element, "displacement 2", f)
p = Problem(Dirichlet, "test boundary", 2, "displacement")
push!(p, element)
assemble!(p, 0.0)
g1 = full(p.assembly.g, 4, 1)
@test isapprox(g1, [0.0, 0.0, 0.0, 0.0])
empty!(p.assembly)
assemble!(p, 1.0)
g2 = full(p.assembly.g, 4, 1)
C2 = full(p.assembly.C2, 4, 4)
u = C2 \ g2
info("u = $u")
@test isapprox(u, [0.0, 0.0, 0.0, 1.0])
end
@@ -3,14 +3,17 @@
using JuliaFEM
using JuliaFEM.Preprocess
using JuliaFEM.Postprocess
using JuliaFEM.Test
using JLD
@testset "test 2d linear elasticity with surface load" begin
function JuliaFEM.get_model(::Type{Val{Symbol("test 2d linear elasticity with surface + volume load")}})
meshfile = "/geometry/2d_block/BLOCK_1elem.med"
mesh = aster_read_mesh(Pkg.dir("JuliaFEM")*meshfile)
# field problem
block = Problem(Elasticity, "BLOCK", 2)
block.properties.store_fields = ["stress", "strain"]
block.properties.formulation = :plane_stress
block.properties.finite_strain = false
block.properties.geometric_stiffness = false
@@ -34,6 +37,13 @@ using JuliaFEM.Test
solver = Solver("solve block problem")
push!(solver, block, bc_sym)
return solver
end
@testset "test 2d linear elasticity with surface + volume load" begin
solver = get_model("test 2d linear elasticity with surface + volume load")
block, bc_sym = solver.problems
call(solver)
f = 288.0
@@ -49,14 +59,39 @@ using JuliaFEM.Test
for ip in get_integration_points(block.elements[1])
eps = ip("strain")
@printf "%i | %8.3f %8.3f | %8.3f %8.3f %8.3f\n" ip.id ip.coords[1] ip.coords[2] eps[1] eps[2] eps[3]
@test isapprox(eps, [u3; 0.0])
@test isapprox(eps, [u3[1], u3[2], 0.0])
end
info("stress")
for ip in get_integration_points(block.elements[1])
sig = ip("stress")
@printf "%i | %8.3f %8.3f | %8.3f %8.3f %8.3f\n" ip.id ip.coords[1] ip.coords[2] sig[1] sig[2] sig[3]
@test isapprox(sig, [0.0; g; 0.0])
@test isapprox(sig, [0.0, g, 0.0])
end
calc_nodal_values!(block.elements, "strain", 3, 0.0)
calc_nodal_values!(block.elements, "stress", 3, 0.0)
info(block.elements[1]["stress"](0.0))
node_ids, strain = get_nodal_vector(block.elements, "strain", 0.0)
node_ids, stress = get_nodal_vector(block.elements, "stress", 0.0)
@test isapprox(stress[1], [0.0, g, 0.0])
@test isapprox(strain[1], [u3[1], u3[2], 0.0])
end
@testset "test dump model to disk and read back before and after solution" begin
solver = get_model("test 2d linear elasticity with surface + volume load")
save("/tmp/model.jld", "linear_model", solver)
solver2 = load("/tmp/model.jld")["linear_model"]
call(solver2)
save("/tmp/model.jld", "results", solver2)
solver3 = load("/tmp/model.jld")["results"]
block = solver3["BLOCK"]
u3 = reshape(block.assembly.u, 2, 4)[:,3]
f = 288.0
g = 576.0
E = 288.0
nu = 1/3
u3_expected = f/E*[-nu, 1] + g/(2*E)*[-nu, 1]
@test isapprox(u3, u3_expected)
end
+30 -1
View File
@@ -59,7 +59,7 @@ end
=#
@testset "test add time dependent field to element" begin
@testset "add time dependent field to element" begin
el = Element(Seg2, [1, 2])
u1 = Vector{Float64}[[0.0, 0.0], [0.0, 0.0]]
u2 = Vector{Float64}[[1.0, 1.0], [1.0, 1.0]]
@@ -69,5 +69,34 @@ end
@test isapprox(el("displacement", [0.0], 0.0), [0.0, 0.0])
@test isapprox(el("displacement", [0.0], 0.5), [0.5, 0.5])
@test isapprox(el("displacement", [0.0], 1.0), [1.0, 1.0])
el2 = Element(Poi1, [1])
update!(el2, "force 1", 0.0 => 1.0)
end
@testset "add CVTV field to element" begin
el = Element(Seg2, [1, 2])
f(xi, time) = xi[1]*time
update!(el, "my field", f)
v = el("my field", [1.0], 2.0)
@test isapprox(v, 2.0)
end
@testset "add DCTI to element" begin
el = Element(Quad4, [1, 2, 3, 4])
update!(el, "displacement load", DCTI([4.0, 8.0]))
@test isa(el["displacement load"], DCTI)
@test !isa(el["displacement load"].data, DCTI)
update!(el, "displacement load 2", [4.0, 8.0])
@test isa(el["displacement load 2"], DCTI)
update!(el, "temperature", [1.0, 2.0, 3.0, 4.0])
@test isa(el["temperature"], DVTI)
end
@testset "interpolate DCTI from element" begin
el = Element(Seg2, [1, 2])
update!(el, "foobar", 1.0)
fb = el("foobar", [0.0], 0.0)
@test isa(fb, Float64)
@test isapprox(fb, 1.0)
end
+6
View File
@@ -25,3 +25,9 @@ end
@test f.data == 2.0
end
@testset "test field defined using function" begin
g(xi, t) = xi[1]*t
f = Field(g)
v = f([1.0], 2.0)
@test isapprox(v, 2.0)
end
+3 -5
View File
@@ -45,7 +45,6 @@ end
p1, p2, p3, p4 = get_test_model()
p1.properties.formulation = :plane_stress
p2.properties.formulation = :plane_stress
p4.properties.dimension = 1
p4.properties.adjust = true
p4.properties.rotate_normals = false
solver = Solver(Nonlinear)
@@ -82,7 +81,6 @@ end
interface_master_elements = create_elements(mesh, "UPPER_BOTTOM")
update!(interface_slave_elements, "master elements", interface_master_elements)
interface.elements = [interface_master_elements; interface_slave_elements]
interface.properties.dimension = 1
solver = Solver()
push!(solver, upper, lower, bc_upper, bc_lower, interface)
@@ -186,7 +184,7 @@ end
function JuliaFEM.get_model(::Type{Val{Symbol("mesh tie with curved 2d block")}};
dy=0.0, adjust=false, tolerance=0.0, rotate_normals=false, swap=false,
dual_basis=false)
dual_basis=false, use_forwarddiff=false)
mesh = get_mesh("curved 2d block splitted to upper and lower")
@@ -221,9 +219,10 @@ function JuliaFEM.get_model(::Type{Val{Symbol("mesh tie with curved 2d block")}}
update!(interface_slave_elements, "master elements", interface_master_elements)
interface.elements = [interface_master_elements; interface_slave_elements]
interface.properties.adjust = adjust
interface.properties.tolerance = tolerance
interface.properties.distval = tolerance
interface.properties.rotate_normals = rotate_normals
interface.properties.dual_basis = dual_basis
interface.properties.use_forwarddiff = use_forwarddiff
solver = Solver(Nonlinear)
push!(solver, upper, lower, bc_upper, bc_lower, interface)
@@ -276,4 +275,3 @@ end
@test solver.properties.iteration == 2
@test isapprox(norm(interface.assembly.u), 0.34318800698017704)
end
+195
View File
@@ -0,0 +1,195 @@
# 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
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"
mesh = aster_read_mesh(meshfile)
end
function JuliaFEM.get_model(::Type{Val{Symbol("mesh tie with curved 2d block")}};
dy=0.0, adjust=false, tolerance=0.0, rotate_normals=false, swap=false,
dual_basis=false, use_forwarddiff=true, finite_strain=false,
geometric_stiffness=false)
mesh = get_mesh("curved 2d block splitted to upper and lower")
upper = Problem(Elasticity, "upper", 2)
upper.properties.formulation = :plane_stress
upper.properties.finite_strain = finite_strain
upper.properties.geometric_stiffness = geometric_stiffness
upper.elements = create_elements(mesh, "UPPER")
update!(upper.elements, "youngs modulus", 96.0)
update!(upper.elements, "poissons ratio", 1/3)
lower = Problem(Elasticity, "lower", 2)
lower.properties.formulation = :plane_stress
lower.properties.finite_strain = finite_strain
lower.properties.geometric_stiffness = geometric_stiffness
lower.elements = create_elements(mesh, "LOWER")
update!(lower.elements, "youngs modulus", 96.0)
update!(lower.elements, "poissons ratio", 1/3)
bc_upper = Problem(Dirichlet, "upper boundary", 2, "displacement")
bc_upper.elements = create_elements(mesh, "UPPER_TOP")
update!(bc_upper.elements, "displacement 1", 0.0)
update!(bc_upper.elements, "displacement 2", dy)
bc_lower = Problem(Dirichlet, "lower boundary", 2, "displacement")
bc_lower.elements = create_elements(mesh, "LOWER_BOTTOM")
update!(bc_lower.elements, "displacement 1", 0.0)
update!(bc_lower.elements, "displacement 2", 0.0)
interface = Problem(Mortar, "interface between upper and lower block", 2, "displacement")
interface_slave_elements = create_elements(mesh, "LOWER_TOP")
interface_master_elements = create_elements(mesh, "UPPER_BOTTOM")
if swap
interface_slave_elements, interface_master_elements = interface_master_elements, interface_slave_elements
end
update!(interface_slave_elements, "master elements", interface_master_elements)
interface.elements = [interface_master_elements; interface_slave_elements]
interface.properties.adjust = adjust
interface.properties.distval = tolerance
interface.properties.rotate_normals = rotate_normals
interface.properties.dual_basis = dual_basis
interface.properties.use_forwarddiff = use_forwarddiff
interface.assembly.u = zeros(2*length(mesh.nodes))
interface.assembly.la = zeros(2*length(mesh.nodes))
solver = Solver(Nonlinear)
push!(solver, upper, lower, bc_upper, bc_lower, interface)
return solver
end
@testset "curved surface with adjust=true, standard lagrange, slave=lower surface, dy=0.0" begin
# TODO: analytical solution now known, verify using other fem software
solver = get_model("mesh tie with curved 2d block";
adjust=false, tolerance=10, dy=-0.1, rotate_normals=true,
dual_basis=true, use_forwarddiff=true, finite_strain=true,
geometric_stiffness=true)
call(solver)
interface = solver["interface between upper and lower block"]
@test solver.properties.iteration == 2
@test isapprox(norm(interface.assembly.u), 0.11339715157447851)
end
#=
@testset "curved surface with adjust=true, dual lagrange, slave=lower surface, dy=0.0" begin
# TODO: analytical solution now known, verify using other fem software
solver = get_model("mesh tie with curved 2d block";
adjust=true, tolerance=10, dy=0.0, rotate_normals=true,
dual_basis=true, use_forwarddiff=true)
call(solver)
interface = solver["interface between upper and lower block"]
@test solver.properties.iteration == 2
# differs -- why?
@test isapprox(norm(interface.assembly.u), 0.11660422877751599)
end
@testset "curved surface with adjust=true, standard lagrange, slave=lower surface, dy=-0.1" begin
# TODO: analytical solution now known, verify using other fem software
solver = get_model("mesh tie with curved 2d block";
adjust=true, tolerance=10, dy=-0.1, rotate_normals=true,
dual_basis=false, use_forwarddiff=true)
call(solver)
interface = solver["interface between upper and lower block"]
@test solver.properties.iteration == 2
@test isapprox(norm(interface.assembly.u), 0.34230262165505887)
end
@testset "curved surface, adjust=true, dual basis, slave=lower surface, dy=-0.1" begin
# TODO: analytical solution now known, verify using other fem software
solver = get_model("mesh tie with curved 2d block";
adjust=true, tolerance=10, dy=-0.1, rotate_normals=true,
dual_basis=true, use_forwarddiff=true)
call(solver)
interface = solver["interface between upper and lower block"]
@test solver.properties.iteration == 2
@test isapprox(norm(interface.assembly.u), 0.34318800698017704)
end
=#
function Base.isapprox(A::SparseMatrixCOO, B::SparseMatrixCOO)
A2 = sparse(A)
B2 = sparse(B, size(A2)...)
return isapprox(A2, B2)
end
function Base.isapprox(a1::Assembly, a2::Assembly)
T = isapprox(a1.K, a2.K)
T &= isapprox(a1.C1, a2.C1)
T &= isapprox(a1.C2, a2.C2)
T &= isapprox(a1.D, a2.D)
T &= isapprox(a1.f, a2.f)
T &= isapprox(a1.g, a2.g)
return T
end
@testset "compare forwarddiff solution to normal" begin
X = Dict(
1 => [0.0, 0.0],
2 => [1.0, 0.0],
3 => [0.0, 1.0],
4 => [1.0, 1.0])
u = Dict(
1 => [0.0, 0.0],
2 => [0.0, 0.0],
3 => [0.0, 0.0],
4 => [0.0, 0.0])
sel1 = Element(Seg2, [1, 2])
mel1 = Element(Seg2, [3, 4])
update!([sel1, mel1], "geometry", X)
update!([sel1, mel1], "displacement", u)
update!(sel1, "master elements", [mel1])
p1 = Problem(Mortar, "test 1", 2, "displacement")
p2 = Problem(Mortar, "test 2", 2, "displacement")
push!(p1, sel1, mel1)
push!(p2, sel1, mel1)
#p1.properties.adjust = true
p2.properties.use_forwarddiff = true
#p1.properties.dual_basis = true
#p2.properties.dual_basis = true
p2.assembly.u = zeros(8)
p2.assembly.la = zeros(8)
assemble!(p1, 0.0)
assemble!(p2, 0.0)
@test isapprox(p1.assembly, p2.assembly)
empty!(p1.assembly)
empty!(p2.assembly)
p1.properties.adjust = true
p2.properties.adjust = true
assemble!(p1, 0.0)
assemble!(p2, 0.0)
C11 = full(p1.assembly.C1, 4, 8)
C12 = full(p2.assembly.C1, 4, 8)
C21 = full(p1.assembly.C2, 4, 8)
C22 = full(p2.assembly.C2, 4, 8)
D1 = full(p1.assembly.D)
D2 = full(p2.assembly.D)
g1 = full(p1.assembly.g, 4, 1)
g2 = full(p2.assembly.g, 4, 1)
println("C1")
dump(C11)
dump(C12)
println("C2")
dump(C21)
dump(C22)
println("D")
dump(D1)
dump(D2)
println("g")
dump(g1)
dump(g2)
@test isapprox(p1.assembly, p2.assembly)
end
+27 -2
View File
@@ -1,8 +1,6 @@
# This file is a part of JuliaFEM.
# License is MIT: see https://github.com/JuliaFEM/JuliaFEM.jl/blob/master/LICENSE.md
module XDMFTests
using JuliaFEM
using JuliaFEM.Postprocess
using JuliaFEM.Test
@@ -126,4 +124,31 @@ function test_write_to_xml()
end
end
@testset "write simple xmf file" begin
X = Dict{Int64, Vector{Float64}}(
1 => [0.0, 0.0],
2 => [1.0, 0.0],
3 => [1.0, 1.0],
4 => [0.0, 1.0])
u = Dict{Int64, Vector{Float64}}(
1 => [0.0, 0.0],
2 => [0.0, 0.0],
3 => [0.5, 1.0],
4 => [0.0, 0.0])
n = Dict{Int64, Vector{Float64}}(
2 => [1.0, 0.0],
3 => [1.0, 0.0])
el1 = Element(Quad4, [1, 2, 3, 4])
el2 = Element(Seg2, [2, 3])
update!([el1, el2], "geometry", X)
update!([el1, el2], "displacement", u)
update!(el2, "normal", n)
xdmf = XDMF()
xdmf.dimension = 2
xdmf_new_result!(xdmf, [el1, el2], 0.0)
xdmf_save_field!(xdmf, [el1, el2], 0.0, "displacement"; field_type="Vector")
xdmf_save_field!(xdmf, [el1, el2], 0.0, "normal"; field_type="Vector")
xdmf_save!(xdmf, "/tmp/test.xmf")
# TODO: how to test?
end