mirror of
https://github.com/JuliaFEM/JuliaFEM.jl.git
synced 2026-09-19 09:54:55 +00:00
code refactoring
This commit is contained in:
@@ -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
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
|
||||
Reference in New Issue
Block a user