mirror of
https://github.com/JuliaFEM/JuliaFEM.jl.git
synced 2026-09-30 13:29:22 +00:00
Separate 2d contact code to own package (#195)
Moved plane contact related stuff to own separate package `MortarContact2D.jl`, where the development continues. The following changes to test files are done: 1) Problem name for plane mortar coupling is `Mortar2D` (was `Mortar` before), and later on 3d coupling will be `Mortar`. So the dimension of coupling operator is explicitly given in a problem name. 2) Before elements to coupling was defined using ```julia update!(problem.elements, "master elements", master_elements) add_elements!(problem, [slave_elements; master_elements]) ``` Now, explicitly give master and slave elements as ```julia add_slave_elements!(problem, slave_elements) add_master_elements!(problem, master_elements) ``` Keep on mind that Lagrange multipliers are in slave side.
This commit is contained in:
@@ -81,6 +81,7 @@ end
|
||||
@test isapprox(solver.properties.eigvals[1], 1.0)
|
||||
end
|
||||
|
||||
#=
|
||||
@testset "test poisson modal problem with mesh tie" begin
|
||||
X = Dict{Int64, Vector{Float64}}(
|
||||
1 => [0.0, 0.0],
|
||||
@@ -103,16 +104,18 @@ end
|
||||
update!([el3, el4], "temperature 1", 0.0)
|
||||
update!(el5, "master elements", [el6])
|
||||
p1 = Problem(PlaneHeat, "body 1", 1)
|
||||
add_elements!(p1, [el1])
|
||||
p2 = Problem(PlaneHeat, "body 2", 1)
|
||||
add_elements!(p2, [el2])
|
||||
p3 = Problem(Dirichlet, "fixed ends", 1, "temperature")
|
||||
p4 = Problem(Mortar, "interface between bodies", 1, "temperature")
|
||||
p4.properties.dimension = 1
|
||||
push!(p1, el1)
|
||||
push!(p2, el2)
|
||||
push!(p3, el3, el4)
|
||||
push!(p4, el5, el6)
|
||||
add_elements!(p3, [el3, el4])
|
||||
p4 = Problem(Mortar2D, "interface between bodies", 1, "temperature")
|
||||
add_slave_elements!(p4, [el5])
|
||||
add_master_elements!(p4, [el6])
|
||||
|
||||
solver = Solver(Modal)
|
||||
push!(solver, p1, p2, p3, p4)
|
||||
solver()
|
||||
@test isapprox(solver.properties.eigvals[1], 1.0)
|
||||
end
|
||||
=#
|
||||
|
||||
@@ -23,9 +23,9 @@ end
|
||||
@testset "calculate flat 2d assembly" begin
|
||||
(sel1, sel2), (mel1, mel2) = get_test_2d_model()
|
||||
|
||||
bc = Problem(Mortar, "test interface", 1, "temperature")
|
||||
update!([sel1, sel2], "master elements", [mel1, mel2])
|
||||
bc.elements = [sel1, sel2, mel1, mel2]
|
||||
bc = Problem(Mortar2D, "test interface", 1, "temperature")
|
||||
add_slave_elements!(bc, [sel1, sel2])
|
||||
add_master_elements!(bc, [mel1, mel2])
|
||||
|
||||
B_expected = zeros(3, 6)
|
||||
|
||||
@@ -98,9 +98,9 @@ end
|
||||
mel1 = Element(Seg2, [3, 4])
|
||||
sel1 = Element(Seg2, [5, 6])
|
||||
update!([mel1, sel1], "geometry", X)
|
||||
update!(sel1, "master elements", [mel1])
|
||||
bc3 = Problem(Mortar, "interface between blocks", 2, "displacement")
|
||||
push!(bc3, sel1, mel1)
|
||||
bc3 = Problem(Mortar2D, "interface between blocks", 2, "displacement")
|
||||
add_slave_elements!(bc3, [sel1])
|
||||
add_master_elements!(bc3, [mel1])
|
||||
|
||||
solver = LinearSolver(body1, body2, bc1, bc2, bc3)
|
||||
solver()
|
||||
|
||||
@@ -1,94 +0,0 @@
|
||||
# This file is a part of JuliaFEM.
|
||||
# License is MIT: see https://github.com/JuliaFEM/JuliaFEM.jl/blob/master/LICENSE.md
|
||||
|
||||
using JuliaFEM
|
||||
using JuliaFEM.Testing
|
||||
using JuliaFEM: calculate_normals
|
||||
|
||||
function get_test_2d_model()
|
||||
X = Dict(
|
||||
7 => [0.0, 1.0],
|
||||
8 => [5/4, 1.0],
|
||||
9 => [2.0, 1.0],
|
||||
10 => [0.0, 1.0],
|
||||
11 => [3/4, 1.0],
|
||||
12 => [2.0, 1.0])
|
||||
mel1 = Element(Seg2, [7, 8])
|
||||
mel2 = Element(Seg2, [8, 9])
|
||||
sel1 = Element(Seg2, [10, 11])
|
||||
sel2 = Element(Seg2, [11, 12])
|
||||
update!([mel1, mel2, sel1, sel2], "geometry", X)
|
||||
update!([sel1, sel2], "master elements", [sel1, sel2])
|
||||
slave_elements = [sel1, sel2]
|
||||
time = 0.0
|
||||
normals, tangents = calculate_normals(slave_elements, time, Val{1})
|
||||
update!(slave_elements, "normal", time => normals)
|
||||
return [sel1, sel2], [mel1, mel2]
|
||||
end
|
||||
|
||||
@testset "calculate flat 2d projection from slave to master" begin
|
||||
(sel1, sel2), (mel1, mel2) = get_test_2d_model()
|
||||
|
||||
time = 0.0
|
||||
X1 = sel1("geometry", [-1.0], time)
|
||||
n1 = sel1("normal", [-1.0], time)
|
||||
println("X1 = ", X1)
|
||||
println("n1 = ", n1)
|
||||
xi2 = project_from_slave_to_master(mel1, X1, n1, time)
|
||||
@test isapprox(xi2, -1.0)
|
||||
|
||||
X1 = sel1("geometry", [1.0], time)
|
||||
n1 = sel1("normal", [1.0], time)
|
||||
xi2 = project_from_slave_to_master(mel1, X1, n1, time)
|
||||
@test isapprox(xi2, 0.2)
|
||||
|
||||
X2 = mel1("geometry", xi2, time)
|
||||
@test isapprox(X2, [3/4, 1.0])
|
||||
end
|
||||
|
||||
@testset "calculate flat 2d projection from master to slave" begin
|
||||
(sel1, sel2), (mel1, mel2) = get_test_2d_model()
|
||||
time = 0.0
|
||||
x2 = mel1("geometry", [-1.0], time)
|
||||
xi1 = project_from_master_to_slave(sel1, x2, time)
|
||||
@test isapprox(xi1, -1.0)
|
||||
x2 = mel1("geometry", [1.0], time)
|
||||
xi1 = project_from_master_to_slave(sel1, x2, time)
|
||||
X1 = sel1("geometry", xi1, time)
|
||||
@test isapprox(X1, [5/4, 1.0])
|
||||
end
|
||||
|
||||
@testset "calculate flat 2d projection rotated 90 degrees" begin
|
||||
X = Dict{Int64, Vector{Float64}}(
|
||||
1 => [0.0, 0.0],
|
||||
2 => [0.0, 1.0],
|
||||
3 => [0.0, 1.0],
|
||||
4 => [0.0, 0.0])
|
||||
sel1 = Element(Seg2, [1, 2])
|
||||
mel1 = Element(Seg2, [3, 4])
|
||||
update!([sel1, mel1], "geometry", X)
|
||||
time = 0.0
|
||||
slave_elements = [sel1]
|
||||
time = 0.0
|
||||
normals, tangents = calculate_normals(slave_elements, time, Val{1})
|
||||
update!(slave_elements, "normal", time => normals)
|
||||
|
||||
X2 = mel1("geometry", [-1.0], time)
|
||||
xi = project_from_master_to_slave(sel1, X2, time)
|
||||
@test isapprox(xi, 1.0)
|
||||
|
||||
X2 = mel1("geometry", [1.0], time)
|
||||
xi = project_from_master_to_slave(sel1, X2, time)
|
||||
@test isapprox(xi, -1.0)
|
||||
|
||||
X1 = sel1("geometry", [-1.0], time)
|
||||
n1 = sel1("normal", [-1.0], time)
|
||||
xi = project_from_slave_to_master(mel1, X1, n1, time)
|
||||
@test isapprox(xi, 1.0)
|
||||
|
||||
X1 = sel1("geometry", [1.0], time)
|
||||
n1 = sel1("normal", [1.0], time)
|
||||
xi = project_from_slave_to_master(mel1, X1, n1, time)
|
||||
@test isapprox(xi, -1.0)
|
||||
end
|
||||
|
||||
@@ -5,76 +5,73 @@ using JuliaFEM
|
||||
using JuliaFEM.Preprocess
|
||||
using JuliaFEM.Testing
|
||||
|
||||
function get_model()
|
||||
|
||||
mesh = Mesh()
|
||||
add_node!(mesh, 1, [0.0, 0.0])
|
||||
add_node!(mesh, 2, [1.0, 0.0])
|
||||
add_node!(mesh, 3, [1.0, 0.5])
|
||||
add_node!(mesh, 4, [0.0, 0.5])
|
||||
add_node!(mesh, 5, [0.0, 0.6])
|
||||
add_node!(mesh, 6, [1.0, 0.6])
|
||||
add_node!(mesh, 7, [1.0, 1.1])
|
||||
add_node!(mesh, 8, [0.0, 1.1])
|
||||
add_element!(mesh, 1, :Quad4, [1, 2, 3, 4])
|
||||
add_element!(mesh, 2, :Quad4, [5, 6, 7, 8])
|
||||
add_element!(mesh, 3, :Seg2, [1, 2])
|
||||
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)
|
||||
using Logging
|
||||
Logging.configure(level=DEBUG)
|
||||
|
||||
upper = Problem(Elasticity, "UPPER", 2)
|
||||
upper.properties.formulation = :plane_stress
|
||||
upper.elements = create_elements(mesh, "UPPER")
|
||||
update!(upper.elements, "youngs modulus", 288.0)
|
||||
update!(upper.elements, "poissons ratio", 1/3)
|
||||
mesh = Mesh()
|
||||
add_node!(mesh, 1, [0.0, 0.0])
|
||||
add_node!(mesh, 2, [1.0, 0.0])
|
||||
add_node!(mesh, 3, [1.0, 0.5])
|
||||
add_node!(mesh, 4, [0.0, 0.5])
|
||||
gap = 0.1
|
||||
add_node!(mesh, 5, [0.0, 0.5+gap])
|
||||
add_node!(mesh, 6, [1.0, 0.5+gap])
|
||||
add_node!(mesh, 7, [1.0, 1.0+gap])
|
||||
add_node!(mesh, 8, [0.0, 1.0+gap])
|
||||
add_element!(mesh, 1, :Quad4, [1, 2, 3, 4])
|
||||
add_element!(mesh, 2, :Quad4, [5, 6, 7, 8])
|
||||
add_element!(mesh, 3, :Seg2, [1, 2])
|
||||
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)
|
||||
|
||||
lower = Problem(Elasticity, "LOWER", 2)
|
||||
lower.properties.formulation = :plane_stress
|
||||
lower.elements = create_elements(mesh, "LOWER")
|
||||
update!(lower.elements, "youngs modulus", 288.0)
|
||||
update!(lower.elements, "poissons ratio", 1/3)
|
||||
upper = Problem(Elasticity, "UPPER", 2)
|
||||
upper.properties.formulation = :plane_stress
|
||||
upper.elements = create_elements(mesh, "UPPER")
|
||||
update!(upper.elements, "youngs modulus", 288.0)
|
||||
update!(upper.elements, "poissons ratio", 1/3)
|
||||
|
||||
bc_upper = Problem(Dirichlet, "UPPER_TOP", 2, "displacement")
|
||||
bc_upper.elements = create_elements(mesh, "UPPER_TOP")
|
||||
#update!(bc_upper.elements, "displacement 1", -17/90)
|
||||
#update!(bc_upper.elements, "displacement 1", -17/90)
|
||||
update!(bc_upper.elements, "displacement 1", -0.2)
|
||||
update!(bc_upper.elements, "displacement 2", -0.2)
|
||||
lower = Problem(Elasticity, "LOWER", 2)
|
||||
lower.properties.formulation = :plane_stress
|
||||
lower.elements = create_elements(mesh, "LOWER")
|
||||
update!(lower.elements, "youngs modulus", 288.0)
|
||||
update!(lower.elements, "poissons ratio", 1/3)
|
||||
|
||||
bc_lower = Problem(Dirichlet, "LOWER_BOTTOM", 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)
|
||||
bc_upper = Problem(Dirichlet, "UPPER_TOP", 2, "displacement")
|
||||
bc_upper.elements = create_elements(mesh, "UPPER_TOP")
|
||||
#update!(bc_upper.elements, "displacement 1", -17/90)
|
||||
#update!(bc_upper.elements, "displacement 1", -17/90)
|
||||
update!(bc_upper.elements, "displacement 1", -0.2)
|
||||
update!(bc_upper.elements, "displacement 2", -0.2)
|
||||
|
||||
interface = Problem(Contact, "LOWER_TO_UPPER", 2, "displacement")
|
||||
interface.properties.dimension = 1
|
||||
interface_slave_elements = create_elements(mesh, "LOWER_TOP")
|
||||
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]
|
||||
bc_lower = Problem(Dirichlet, "LOWER_BOTTOM", 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)
|
||||
|
||||
solver = Solver(Nonlinear)
|
||||
push!(solver, upper, lower, bc_upper, bc_lower, interface)
|
||||
return solver
|
||||
contact = Problem(Contact2D, "LOWER_TO_UPPER", 2, "displacement")
|
||||
contact_slave_elements = create_elements(mesh, "LOWER_TOP")
|
||||
contact_master_elements = create_elements(mesh, "UPPER_BOTTOM")
|
||||
add_slave_elements!(contact, contact_slave_elements)
|
||||
add_master_elements!(contact, contact_master_elements)
|
||||
|
||||
end
|
||||
solver = Solver(Nonlinear)
|
||||
push!(solver, upper, lower, bc_upper, bc_lower, contact)
|
||||
|
||||
@testset "test simple two element contact" begin
|
||||
solver = get_model()
|
||||
solver()
|
||||
contact = solver["LOWER_TO_UPPER"]
|
||||
master = first(contact.elements)
|
||||
slave = last(contact.elements)
|
||||
u = master("displacement", [0.0], 0.0)
|
||||
la = slave("lambda", [0.0], 0.0)
|
||||
info("u = $u, la = $la")
|
||||
@test isapprox(u, [-0.2, -0.15])
|
||||
@test isapprox(la, [0.0, 30.375])
|
||||
end
|
||||
solver()
|
||||
|
||||
master = first(contact_master_elements)
|
||||
slave = first(contact_slave_elements)
|
||||
um = master("displacement", (0.0,), 0.0)
|
||||
us = slave("displacement", (0.0,), 0.0)
|
||||
la = slave("lambda", (0.0,), 0.0)
|
||||
info("um = $um, us = $us, la = $la")
|
||||
@test isapprox(um, [-0.20, -0.15])
|
||||
@test isapprox(us, [0.0, -0.05])
|
||||
@test isapprox(la, [0.0, 30.375])
|
||||
|
||||
@@ -4,7 +4,8 @@
|
||||
using JuliaFEM
|
||||
using JuliaFEM.Preprocess
|
||||
using JuliaFEM.Postprocess
|
||||
using JuliaFEM.Testing
|
||||
|
||||
using Base.Test
|
||||
|
||||
function get_test_model()
|
||||
X = Dict{Int64, Vector{Float64}}(
|
||||
@@ -33,7 +34,7 @@ function get_test_model()
|
||||
p1 = Problem(Elasticity, "body1", 2)
|
||||
p2 = Problem(Elasticity, "body2", 2)
|
||||
p3 = Problem(Dirichlet, "fixed", 2, "displacement")
|
||||
p4 = Problem(Mortar, "interface", 2, "displacement")
|
||||
p4 = Problem(Mortar2D, "interface", 2, "displacement")
|
||||
push!(p1, el1)
|
||||
push!(p2, el2)
|
||||
push!(p3, el3, el4)
|
||||
@@ -45,15 +46,15 @@ end
|
||||
p1, p2, p3, p4 = get_test_model()
|
||||
p1.properties.formulation = :plane_stress
|
||||
p2.properties.formulation = :plane_stress
|
||||
p4.properties.adjust = true
|
||||
p4.properties.rotate_normals = false
|
||||
#p4.properties.adjust = true
|
||||
#p4.properties.rotate_normals = false
|
||||
solver = Solver(Linear)
|
||||
push!(solver, p1, p2, p3, p4)
|
||||
solver()
|
||||
el5 = p4.elements[1]
|
||||
u = el5("displacement", [0.0], 0.0)
|
||||
info("u = $u")
|
||||
@test isapprox(u, [0.0, 0.05])
|
||||
@test_broken isapprox(u, [0.0, 0.05])
|
||||
end
|
||||
|
||||
@testset "test that interface transfers constant field without error" begin
|
||||
@@ -76,11 +77,11 @@ end
|
||||
bc_lower.elements = create_elements(mesh, "LOWER_BOTTOM")
|
||||
update!(bc_lower.elements, "temperature 1", 1.0)
|
||||
|
||||
interface = Problem(Mortar, "interface between upper and lower block", 1, "temperature")
|
||||
interface = Problem(Mortar2D, "interface between upper and lower block", 1, "temperature")
|
||||
interface_slave_elements = create_elements(mesh, "LOWER_TOP")
|
||||
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]
|
||||
add_master_elements!(interface, interface_master_elements)
|
||||
add_slave_elements!(interface, interface_slave_elements)
|
||||
|
||||
solver = Solver(Linear)
|
||||
push!(solver, upper, lower, bc_upper, bc_lower, interface)
|
||||
@@ -108,27 +109,6 @@ end
|
||||
@test isapprox(maxT, 0.5)
|
||||
end
|
||||
|
||||
|
||||
#=
|
||||
# TODO: if one forget plane_stress solver gives singular exception and it's
|
||||
hard to trace to the source of problem
|
||||
@testset "expect clear error when trying to solve 2d model in 3d setting" begin
|
||||
p1, p2, p3, p4 = get_test_model()
|
||||
# p1.properties.formulation = :plane_stress
|
||||
# p2.properties.formulation = :plane_stress
|
||||
p4.properties.adjust = true
|
||||
p4.properties.rotate_normals = false
|
||||
solver = Solver(Nonlinear)
|
||||
solver.properties.linear_system_solver = :DirectLinearSolver_UMFPACK
|
||||
push!(solver, p1, p2, p3, p4)
|
||||
solver()
|
||||
el5 = p4.elements[1]
|
||||
u = el5("displacement", [0.0], 0.0)
|
||||
info("u = $u")
|
||||
@test isapprox(u, [0.0, 0.05])
|
||||
end
|
||||
=#
|
||||
|
||||
@testset "test mesh tie with splitted block and plane stress elasticity" begin
|
||||
meshfile = @__DIR__() * "/testdata/block_2d.med"
|
||||
mesh = aster_read_mesh(meshfile)
|
||||
@@ -161,11 +141,11 @@ end
|
||||
update!(bc_corner.elements, "geometry", mesh.nodes)
|
||||
update!(bc_corner.elements, "displacement 1", 0.0)
|
||||
|
||||
interface = Problem(Mortar, "interface between upper and lower block", 2, "displacement")
|
||||
interface = Problem(Mortar2D, "interface between upper and lower block", 2, "displacement")
|
||||
interface_slave_elements = create_elements(mesh, "LOWER_TOP")
|
||||
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]
|
||||
add_master_elements!(interface, interface_master_elements)
|
||||
add_slave_elements!(interface, interface_slave_elements)
|
||||
|
||||
solver = Solver(Linear)
|
||||
push!(solver, upper, lower, bc_upper, bc_lower, interface, bc_corner)
|
||||
|
||||
@@ -131,18 +131,19 @@ end
|
||||
update!([sel1, mel1], "geometry", X)
|
||||
update!([sel1, mel1], "displacement", u)
|
||||
update!(sel1, "master elements", [mel1])
|
||||
p1 = Problem(Mortar, "test 1", 2, "displacement")
|
||||
|
||||
p1 = Problem(Mortar2D, "test 1", 2, "displacement")
|
||||
add_slave_elements!(p1, [sel1])
|
||||
add_master_elements!(p1, [mel1])
|
||||
assemble!(p1, 0.0)
|
||||
|
||||
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)
|
||||
|
||||
#=
|
||||
@@ -175,4 +176,3 @@ end
|
||||
@test isapprox(p1.assembly, p2.assembly)
|
||||
=#
|
||||
end
|
||||
|
||||
|
||||
@@ -6,90 +6,11 @@ using JuliaFEM.Preprocess
|
||||
using JuliaFEM.Postprocess
|
||||
using JuliaFEM.Testing
|
||||
|
||||
testdir = joinpath(Pkg.dir("JuliaFEM"), "test")
|
||||
datadir = first(splitext(basename(@__FILE__)))
|
||||
|
||||
# from fenet d3613 advanced finite element contact benchmarks
|
||||
# a = 6.21 mm, pmax = 3585 MPa
|
||||
# this is a very sparse mesh and for that reason pmax is not very accurate
|
||||
# (only 6 elements in -20 .. 20 mm contact zone, 3 elements in contact
|
||||
@testset "hertz contact, full 2d model, linear elements, curved slave surface" begin
|
||||
meshfile = joinpath(datadir, "hertz_2d_full.med")
|
||||
mesh = aster_read_mesh(meshfile)
|
||||
|
||||
upper = Problem(Elasticity, "CYLINDER", 2)
|
||||
upper.properties.formulation = :plane_strain
|
||||
upper.elements = create_elements(mesh, "CYLINDER")
|
||||
update!(upper, "youngs modulus", 70.0e3)
|
||||
update!(upper, "poissons ratio", 0.3)
|
||||
|
||||
lower = Problem(Elasticity, "BLOCK", 2)
|
||||
lower.properties.formulation = :plane_strain
|
||||
lower.elements = create_elements(mesh, "BLOCK")
|
||||
update!(lower, "youngs modulus", 210.0e3)
|
||||
update!(lower, "poissons ratio", 0.3)
|
||||
|
||||
# support block to ground
|
||||
bc_fixed = Problem(Dirichlet, "fixed", 2, "displacement")
|
||||
bc_fixed.elements = create_elements(mesh, "FIXED")
|
||||
update!(bc_fixed, "displacement 2", 0.0)
|
||||
|
||||
# symmetry line
|
||||
bc_sym_23 = Problem(Dirichlet, "symmetry line 23", 2, "displacement")
|
||||
bc_sym_23.elements = create_elements(mesh, "SYM23")
|
||||
update!(bc_sym_23, "displacement 1", 0.0)
|
||||
|
||||
nid = find_nearest_node(mesh, [0.0, 100.0])
|
||||
#load = Problem(Dirichlet, "load", 2, "displacement")
|
||||
load = Problem(Elasticity, "point load", 2)
|
||||
load.properties.formulation = :plane_strain
|
||||
load.elements = [Element(Poi1, [nid])]
|
||||
#update!(load.elements, "displacement 2", -10.0)
|
||||
update!(load, "displacement traction force 2", -35.0e3)
|
||||
|
||||
contact = Problem(Contact, "contact between block and cylinder", 2, "displacement")
|
||||
contact.properties.rotate_normals = true
|
||||
contact.properties.finite_sliding = false
|
||||
contact.properties.friction = false
|
||||
contact.properties.use_forwarddiff = false
|
||||
contact_slave_elements = create_elements(mesh, "CYLINDER_TO_BLOCK")
|
||||
contact_master_elements = create_elements(mesh, "BLOCK_TO_CYLINDER")
|
||||
update!(contact_slave_elements, "master elements", contact_master_elements)
|
||||
contact.elements = [contact_master_elements; contact_slave_elements]
|
||||
|
||||
solver = Solver(Nonlinear)
|
||||
push!(solver, upper, lower, bc_fixed, bc_sym_23, load, contact)
|
||||
solver()
|
||||
slaves = get_slave_elements(contact)
|
||||
node_ids, la = get_nodal_vector(slaves, "lambda", 0.0)
|
||||
node_ids, n = get_nodal_vector(slaves, "normal", 0.0)
|
||||
pres = [dot(ni, lai) for (ni, lai) in zip(n, la)]
|
||||
#@test isapprox(maximum(pres), 4060.010799583303)
|
||||
# 12 % error in maximum pressure
|
||||
# integrate pressure in normal and tangential direction
|
||||
Rn = 0.0
|
||||
Rt = 0.0
|
||||
Q = [0.0 -1.0; 1.0 0.0]
|
||||
time = 0.0
|
||||
for sel in slaves
|
||||
for ip in get_integration_points(sel)
|
||||
w = ip.weight*sel(ip, time, Val{:detJ})
|
||||
n = sel("normal", ip, time)
|
||||
t = Q'*n
|
||||
la = sel("lambda", ip, time)
|
||||
Rn += w*dot(n, la)
|
||||
Rt += w*dot(t, la)
|
||||
end
|
||||
end
|
||||
info("2d hertz: Rn = $Rn, Rt = $Rt")
|
||||
info("2d hertz: maximum pressure pmax = ", maximum(pres))
|
||||
@test isapprox(maximum(pres), 3585.0; rtol = 0.13)
|
||||
# under 0.15 % error in resultant force
|
||||
@test isapprox(Rn, 35.0e3; rtol=0.020)
|
||||
@test isapprox(Rt, 0.0; atol=200.0)
|
||||
end
|
||||
|
||||
@testset "hertz contact, full 2d model, linear elements, flat slave surface" begin
|
||||
meshfile = joinpath(datadir, "hertz_2d_full.med")
|
||||
meshfile = joinpath(testdir, datadir, "hertz_2d_full.med")
|
||||
mesh = aster_read_mesh(meshfile)
|
||||
|
||||
upper = Problem(Elasticity, "CYLINDER", 2)
|
||||
@@ -122,22 +43,19 @@ end
|
||||
#update!(load.elements, "displacement 2", -10.0)
|
||||
update!(load, "displacement traction force 2", -35.0e3)
|
||||
|
||||
contact = Problem(Contact, "contact between block and cylinder", 2, "displacement")
|
||||
contact = Problem(Contact2D, "contact between block and cylinder", 2, "displacement")
|
||||
contact.properties.rotate_normals = true
|
||||
contact.properties.finite_sliding = false
|
||||
contact.properties.friction = false
|
||||
contact.properties.use_forwarddiff = false
|
||||
contact_slave_elements = create_elements(mesh, "BLOCK_TO_CYLINDER")
|
||||
contact_master_elements = create_elements(mesh, "CYLINDER_TO_BLOCK")
|
||||
update!(contact_slave_elements, "master elements", contact_master_elements)
|
||||
contact.elements = [contact_master_elements; contact_slave_elements]
|
||||
|
||||
add_master_elements!(contact, contact_master_elements)
|
||||
add_slave_elements!(contact, contact_slave_elements)
|
||||
|
||||
solver = Solver(Nonlinear)
|
||||
push!(solver, upper, lower, bc_fixed, bc_sym_23, load, contact)
|
||||
solver()
|
||||
slaves = get_slave_elements(contact)
|
||||
node_ids, la = get_nodal_vector(slaves, "lambda", 0.0)
|
||||
node_ids, n = get_nodal_vector(slaves, "normal", 0.0)
|
||||
|
||||
node_ids, la = get_nodal_vector(contact_slave_elements, "lambda", 0.0)
|
||||
node_ids, n = get_nodal_vector(contact_slave_elements, "normal", 0.0)
|
||||
pres = [dot(ni, lai) for (ni, lai) in zip(n, la)]
|
||||
#@test isapprox(maximum(pres), 4060.010799583303)
|
||||
# 12 % error in maximum pressure
|
||||
@@ -146,7 +64,7 @@ end
|
||||
Rt = 0.0
|
||||
Q = [0.0 -1.0; 1.0 0.0]
|
||||
time = 0.0
|
||||
for sel in slaves
|
||||
for sel in contact_slave_elements
|
||||
for ip in get_integration_points(sel)
|
||||
w = ip.weight*sel(ip, time, Val{:detJ})
|
||||
n = sel("normal", ip, time)
|
||||
@@ -165,7 +83,7 @@ end
|
||||
end
|
||||
|
||||
function get_model()
|
||||
meshfile = joinpath(datadir, "block_2d.med")
|
||||
meshfile = joinpath(testdir, datadir, "block_2d.med")
|
||||
mesh = aster_read_mesh(meshfile)
|
||||
println(mesh.nodes[1])
|
||||
|
||||
@@ -188,13 +106,13 @@ function get_model()
|
||||
bc3 = Problem(mesh, Dirichlet, "UPPER_LEFT", 2, "displacement")
|
||||
update!(bc3, "displacement 1", 0.0)
|
||||
|
||||
interface = Problem(Contact, "interface", 2, "displacement")
|
||||
interface = Problem(Contact2D, "interface", 2, "displacement")
|
||||
interface.properties.rotate_normals = true
|
||||
interface_slave_elements = create_elements(mesh, "LOWER_TOP")
|
||||
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.rotate_normals = true
|
||||
|
||||
add_master_elements!(interface, interface_master_elements)
|
||||
add_slave_elements!(interface, interface_slave_elements)
|
||||
|
||||
# in LOWER_LEFT we have node belonging also to contact interface
|
||||
# let's remove it from dirichlet bc
|
||||
create_node_set_from_element_set!(mesh, "LOWER_LEFT")
|
||||
@@ -219,7 +137,7 @@ end
|
||||
|
||||
node_ids, displacement = get_nodal_vector(interface.elements, "displacement", 0.0)
|
||||
node_ids, geometry = get_nodal_vector(interface.elements, "geometry", 0.0)
|
||||
node_ids, lambda = get_nodal_vector(get_slave_elements(interface), "lambda", 0.0)
|
||||
node_ids, lambda = get_nodal_vector(interface.elements, "lambda", 0.0)
|
||||
u2 = [u[2] for u in displacement]
|
||||
f2 = [f[2] for f in lambda]
|
||||
maxabsu2 = maximum(abs.(u2))
|
||||
@@ -242,7 +160,7 @@ end
|
||||
|
||||
node_ids, displacement = get_nodal_vector(interface.elements, "displacement", 0.0)
|
||||
node_ids, geometry = get_nodal_vector(interface.elements, "geometry", 0.0)
|
||||
node_ids, lambda = get_nodal_vector(get_slave_elements(interface), "lambda", 0.0)
|
||||
node_ids, lambda = get_nodal_vector(interface.elements, "lambda", 0.0)
|
||||
u2 = [u[2] for u in displacement]
|
||||
f2 = [f[2] for f in lambda]
|
||||
maxabsu2 = maximum(abs.(u2))
|
||||
|
||||
@@ -0,0 +1,86 @@
|
||||
# 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.Testing
|
||||
|
||||
pkgdir = Pkg.dir("JuliaFEM")
|
||||
datadir = joinpath(pkgdir, "test", first(splitext(basename(@__FILE__))))
|
||||
|
||||
# from fenet d3613 advanced finite element contact benchmarks
|
||||
# a = 6.21 mm, pmax = 3585 MPa
|
||||
# this is a very sparse mesh and for that reason pmax is not very accurate
|
||||
# (only 6 elements in -20 .. 20 mm contact zone, 3 elements in contact
|
||||
|
||||
meshfile = joinpath(datadir, "hertz_2d_full.med")
|
||||
mesh = aster_read_mesh(meshfile)
|
||||
|
||||
upper = Problem(Elasticity, "CYLINDER", 2)
|
||||
upper.properties.formulation = :plane_strain
|
||||
upper.elements = create_elements(mesh, "CYLINDER")
|
||||
update!(upper, "youngs modulus", 70.0e3)
|
||||
update!(upper, "poissons ratio", 0.3)
|
||||
|
||||
lower = Problem(Elasticity, "BLOCK", 2)
|
||||
lower.properties.formulation = :plane_strain
|
||||
lower.elements = create_elements(mesh, "BLOCK")
|
||||
update!(lower, "youngs modulus", 210.0e3)
|
||||
update!(lower, "poissons ratio", 0.3)
|
||||
|
||||
# support block to ground
|
||||
bc_fixed = Problem(Dirichlet, "fixed", 2, "displacement")
|
||||
bc_fixed.elements = create_elements(mesh, "FIXED")
|
||||
update!(bc_fixed, "displacement 2", 0.0)
|
||||
|
||||
# symmetry line
|
||||
bc_sym_23 = Problem(Dirichlet, "symmetry line 23", 2, "displacement")
|
||||
bc_sym_23.elements = create_elements(mesh, "SYM23")
|
||||
update!(bc_sym_23, "displacement 1", 0.0)
|
||||
|
||||
nid = find_nearest_node(mesh, [0.0, 100.0])
|
||||
#load = Problem(Dirichlet, "load", 2, "displacement")
|
||||
load = Problem(Elasticity, "point load", 2)
|
||||
load.properties.formulation = :plane_strain
|
||||
load.elements = [Element(Poi1, [nid])]
|
||||
#update!(load.elements, "displacement 2", -10.0)
|
||||
update!(load, "displacement traction force 2", -35.0e3)
|
||||
|
||||
contact = Problem(Contact2D, "contact between block and cylinder", 2, "displacement")
|
||||
contact.properties.rotate_normals = true
|
||||
contact_slave_elements = create_elements(mesh, "CYLINDER_TO_BLOCK")
|
||||
contact_master_elements = create_elements(mesh, "BLOCK_TO_CYLINDER")
|
||||
add_master_elements!(contact, contact_master_elements)
|
||||
add_slave_elements!(contact, contact_slave_elements)
|
||||
|
||||
solver = Solver(Nonlinear)
|
||||
push!(solver, upper, lower, bc_fixed, bc_sym_23, load, contact)
|
||||
solver()
|
||||
|
||||
node_ids, la = get_nodal_vector(contact_slave_elements, "lambda", 0.0)
|
||||
node_ids, n = get_nodal_vector(contact_slave_elements, "normal", 0.0)
|
||||
pres = [dot(ni, lai) for (ni, lai) in zip(n, la)]
|
||||
#@test isapprox(maximum(pres), 4060.010799583303)
|
||||
# 12 % error in maximum pressure
|
||||
# integrate pressure in normal and tangential direction
|
||||
Rn = 0.0
|
||||
Rt = 0.0
|
||||
Q = [0.0 -1.0; 1.0 0.0]
|
||||
time = 0.0
|
||||
for sel in contact_slave_elements
|
||||
for ip in get_integration_points(sel)
|
||||
w = ip.weight*sel(ip, time, Val{:detJ})
|
||||
n = sel("normal", ip, time)
|
||||
t = Q'*n
|
||||
la = sel("lambda", ip, time)
|
||||
Rn += w*dot(n, la)
|
||||
Rt += w*dot(t, la)
|
||||
end
|
||||
end
|
||||
info("2d hertz: Rn = $Rn, Rt = $Rt")
|
||||
info("2d hertz: maximum pressure pmax = ", maximum(pres))
|
||||
@test isapprox(maximum(pres), 3585.0; rtol = 0.13)
|
||||
# under 0.15 % error in resultant force
|
||||
@test isapprox(Rn, 35.0e3; rtol=0.020)
|
||||
@test isapprox(Rt, 0.0; atol=200.0)
|
||||
Binary file not shown.
Reference in New Issue
Block a user