Files
JuliaFEM.jl/test/test_problems_contact_2d.jl
T
Jukka Aho b3f0531746 Add postprocessing features (#100)
* refactored code for solvers.

* Added elementary tests for least-squares fitting of strain and stress fields

* A more realistic postprocess + Xdmf writing test

* removed debug keyword argument from test

* Rewrite update_xdmf!

New function to update Xdmf file no longer takes Solver object but
xdmf, problem, time and fields to write, for example

julia> update_xdmf!(xdmf, problem, 0.0, ["displacement", "temperature"])

All problems are written separately and put together into one
SpatialCollection, allowing to have more structured Xdmf and making
it easier to write complicated field configurations. Support for Xdmf
API 3.0 added.

* Support for Tensor6 field writing

* moved update_xdmf! to io.jl

* Removed some empty files

* Not use old Postprocessor, obsolete code.

* Not use old XDMF (obsolete code). Fixed test.

* removed some postprocessing to pass test, maybe we should drop abaqus.jl from code as obsolete

* add function get_temporal_collection back, it's used by update_xdmf of modal solver

* postprocess of boundary problems also

* added test for contact pressure. dl+quad test output was written in wrong file, fixed.

* postprocess for contact pressure

* contact pressure postprocess

* with boundary problems always store also the primary unknown field

* Change "reaction force" -> "lambda"

* testing postprocess of reaction force also

* sign convention
2017-03-21 08:36:18 +02:00

258 lines
10 KiB
Julia

# 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
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")
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, "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]
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
function get_model()
meshfile = joinpath(datadir, "block_2d.med")
mesh = aster_read_mesh(meshfile)
println(mesh.nodes[1])
upper = Problem(mesh, Elasticity, "UPPER", 2)
lower = Problem(mesh, Elasticity, "LOWER", 2)
for body in [upper, lower]
body.properties.formulation = :plane_stress
update!(body, "youngs modulus", 288.0)
update!(body, "poissons ratio", 1/3)
end
load = Problem(mesh, Elasticity, "UPPER_TOP", 2)
load.properties.formulation = :plane_stress
update!(load, "displacement traction force 2", -28.8)
bc1 = Problem(mesh, Dirichlet, "LOWER_BOTTOM", 2, "displacement")
update!(bc1, "displacement 2", 0.0)
bc2 = Problem(mesh, Dirichlet, "LOWER_LEFT", 2, "displacement")
update!(bc2, "displacement 1", 0.0)
bc3 = Problem(mesh, Dirichlet, "UPPER_LEFT", 2, "displacement")
update!(bc3, "displacement 1", 0.0)
interface = Problem(Contact, "interface", 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]
interface.properties.rotate_normals = true
# 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")
nid = find_nearest_node(mesh, [0.0, 0.5]; node_set="LOWER_LEFT")
coords = mesh.nodes[nid]
info("nearest node to (0.0, 0.5) = $nid, coordinates = $coords")
dofs = [2*(nid-1)+1, 2*(nid-1)+2]
info("removing nid $nid, dofs $dofs from LOWER_LEFT")
push!(bc2.assembly.removed_dofs, dofs...)
solver = Solver(Nonlinear)
#push!(solver, upper, lower, load, bc1, interface)
push!(solver, upper, lower, load, bc1, bc2, bc3, interface)
return solver
end
@testset "small sliding 2d patch test, linear Seg2 elements, standard basis" begin
solver = get_model()
interface = solver["interface"]
solver()
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)
u2 = [u[2] for u in displacement]
f2 = [f[2] for f in lambda]
maxabsu2 = maximum(abs(u2))
stdabsu2 = std(abs(u2))
info("max(abs(u2)) = $maxabsu2, std(abs(u2)) = $stdabsu2")
@test isapprox(stdabsu2, 0.0; atol=1.0e-12)
maxabsf2 = maximum(abs(f2))
stdabsf2 = std(abs(f2))
info("max(abs(f2)) = $maxabsf2, std(abs(f2)) = $stdabsf2")
@test isapprox(stdabsf2, 0.0; atol=1.0e-12)
@test isapprox(mean(abs(f2)), 28.8; atol=1.0e-12)
end
@testset "small sliding 2d patch test, linear Seg2 elements, dual basis" begin
solver = get_model()
interface = solver["interface"]
interface.properties.dual_basis = true
solver()
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)
u2 = [u[2] for u in displacement]
f2 = [f[2] for f in lambda]
maxabsu2 = maximum(abs(u2))
stdabsu2 = std(abs(u2))
info("max(abs(u2)) = $maxabsu2, std(abs(u2)) = $stdabsu2")
@test isapprox(stdabsu2, 0.0; atol=1.0e-12)
maxabsf2 = maximum(abs(f2))
stdabsf2 = std(abs(f2))
info("max(abs(f2)) = $maxabsf2, std(abs(f2)) = $stdabsf2")
@test isapprox(stdabsf2, 0.0; atol=1.0e-12)
@test isapprox(mean(abs(f2)), 28.8; atol=1.0e-12)
end