2d finite sliding autodiff version i think it works now

This commit is contained in:
Jukka Aho
2016-07-04 21:47:49 +03:00
parent fac447a862
commit cd891aadda
10 changed files with 188 additions and 116 deletions
+56
View File
@@ -0,0 +1,56 @@
using JuliaFEM
using JuliaFEM.Preprocess
using JuliaFEM.Postprocess
using JuliaFEM.Test
@testset "2d curved block with frictionless finite sliding contact using forwarddiff" begin
# FIXME: needs verification of some other fem software
meshfile = Pkg.dir("JuliaFEM") * "/test/testdata/block_2d_curved.med"
mesh = aster_read_mesh(meshfile)
upper = Problem(Elasticity, "upper", 2)
upper.properties.formulation = :plane_stress
upper.properties.finite_strain = true
upper.properties.geometric_stiffness = true
upper.elements = create_elements(mesh, "UPPER")
update!(upper, "youngs modulus", 96.0)
update!(upper, "poissons ratio", 1/3)
lower = Problem(Elasticity, "lower", 2)
lower.properties.formulation = :plane_stress
lower.properties.finite_strain = true
lower.properties.geometric_stiffness = true
lower.elements = create_elements(mesh, "LOWER")
update!(lower, "youngs modulus", 96.0)
update!(lower, "poissons ratio", 1/3)
bc_upper = Problem(Dirichlet, "upper boundary", 2, "displacement")
bc_upper.elements = create_elements(mesh, "UPPER_TOP")
update!(bc_upper, "displacement 1", 0.0)
update!(bc_upper, "displacement 2", -0.15)
bc_lower = Problem(Dirichlet, "lower boundary", 2, "displacement")
bc_lower.elements = create_elements(mesh, "LOWER_BOTTOM")
update!(bc_lower, "displacement 1", 0.0)
update!(bc_lower, "displacement 2", 0.0)
contact = Problem(Contact, "contact between upper and lower block", 2, "displacement")
contact.properties.rotate_normals = true
contact.properties.finite_sliding = true
contact.properties.friction = false
contact.properties.use_forwarddiff = true
contact_slave_elements = create_elements(mesh, "LOWER_TOP")
contact_master_elements = create_elements(mesh, "UPPER_BOTTOM")
update!(contact_slave_elements, "master elements", contact_master_elements)
contact.elements = [contact_master_elements; contact_slave_elements]
solver = NonlinearSolver(upper, lower, bc_upper, bc_lower, contact)
solver()
normu = norm(contact.assembly.u)
info("displacement vector norm = $normu")
# while accurate solution is unknown this is very close to linear solution
# sqrt( ((Stress 11 - Stress 22)^2 + (Stress 22 - Stress 33)^2 + (Stress 33-Stress 11)^2 + 6*(Stress 12^2 + Stress 23^2 + Stress 13^2))/2 )
# @test isapprox(normu, 0.49745873784105105)
@test isapprox(normu, 0.49745872893844145)
end
+26 -25
View File
@@ -38,16 +38,16 @@ function get_model(::Type{Val{Symbol("curved 2d contact small sliding")}})
update!(bc_lower, "displacement 1", 0.0)
update!(bc_lower, "displacement 2", 0.0)
interface = Problem(Contact, "contact between upper and lower block", 2, "displacement")
interface.properties.dimension = 1
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]
contact = Problem(Contact, "contact between upper and lower block", 2, "displacement")
contact.properties.dimension = 1
contact.properties.rotate_normals = true
contact_slave_elements = create_elements(mesh, "LOWER_TOP")
contact_master_elements = create_elements(mesh, "UPPER_BOTTOM")
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_upper, bc_lower, interface)
push!(solver, upper, lower, bc_upper, bc_lower, contact)
return solver
end
@@ -56,23 +56,13 @@ end
# FIXME: needs verification of some other fem software
solver = get_model("curved 2d contact small sliding")
solver()
upper, lower, bc_upper, bc_lower, interface = solver.problems
@test isapprox(norm(interface.assembly.u), 0.49563347601324315)
end
function get_mesh(::Type{Val{Symbol("hertz contact, full 2d model")}})
meshfile = Pkg.dir("JuliaFEM") * "/test/testdata/hertz_2d_full.med"
mesh = aster_read_mesh(meshfile)
upper, lower, bc_upper, bc_lower, contact = solver.problems
@test isapprox(norm(contact.assembly.u), 0.49563347601324315)
end
function get_model(::Type{Val{Symbol("hertz contact, full 2d model")}})
# 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
# (only 6 elements in -20 .. 20 mm contact zone, 3 elements in contact
# instead integrate pressure in normal and tangential direction
mesh = get_mesh("hertz contact, full 2d model")
meshfile = Pkg.dir("JuliaFEM") * "/test/testdata/hertz_2d_full.med"
mesh = aster_read_mesh(meshfile)
upper = Problem(Elasticity, "CYLINDER", 2)
upper.properties.formulation = :plane_strain
@@ -106,6 +96,9 @@ function get_model(::Type{Val{Symbol("hertz contact, full 2d model")}})
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)
@@ -118,14 +111,21 @@ function get_model(::Type{Val{Symbol("hertz contact, full 2d model")}})
end
@testset "test frictionless hertz contact, 2d plane strain" begin
# 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
# (only 6 elements in -20 .. 20 mm contact zone, 3 elements in contact
# instead integrate pressure in normal and tangential direction
solver = get_model("hertz contact, full 2d model")
solver()
upper, lower, bc_fixed, bc_sym_23, load, contact = solver.problems
solver()
slaves = get_slave_elements(contact)
node_ids, la = get_nodal_vector(slaves, "reaction force", 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)
#@test isapprox(maximum(pres), 4060.010799583303)
# 12 % error in maximum pressure
@test isapprox(maximum(pres), 3585.0; rtol = 12.0e-2)
# integrate pressure in normal and tangential direction
Rn = 0.0
Rt = 0.0
@@ -141,7 +141,8 @@ end
Rt += w*dot(t, la)
end
end
@test isapprox(Rn, 35.0e3; rtol=0.0015)
# under 0.15 % error in reaction force
@test isapprox(Rn, 35.0e3; rtol=0.15e-2)
@test isapprox(Rt, 0.0; atol=10.0)
end
+9 -27
View File
@@ -39,7 +39,7 @@ using JuliaFEM.Postprocess
@test isapprox(T, T_expected; rtol=1.0e-6)
end
@testset "one element heat problem" begin
@testset "2d heat problem (one element)" begin
X = Dict{Int, Vector{Float64}}(
1 => [0.0,0.0],
@@ -65,15 +65,9 @@ end
problem.properties.formulation = "2D"
push!(problem, el1, el2)
# define boundary element for dirichlet boundary condition
el3 = Element(Seg2, [3, 4])
update!(el3, "geometry", X)
update!(el3, "temperature 1", 0.0)
boundary_condition = Problem(Dirichlet, "T=0 on top", 1, "temperature")
push!(boundary_condition, el3)
# manual assembling of problem + solution:
# Set constant source f=12 with k=6. Accurate solution is
# T=1 on free boundary, u(x,y) = -1/6*(1/2*f*x^2 - f*x)
# when boundary flux not active (at t=0)
assemble!(problem, 0.0)
A = full(problem.assembly.K)
b = full(problem.assembly.f)
@@ -86,26 +80,14 @@ end
@test isapprox(A, A_expected)
@test isapprox(A[free_dofs, free_dofs] \ b[free_dofs], [1.0, 1.0])
# using Solver
solver = LinearSolver("solve heat problem")
push!(solver, problem, boundary_condition)
# Set constant source f=12 with k=6. Accurate solution is
# T=1 on free boundary, u(x,y) = -1/6*(1/2*f*x^2 - f*x)
# when boundary flux not active (at t=0)
solver.time = 0.0
solver()
# interpolate temperature at middle of element 2 (flux boundary) at time t=0:
T = el2("temperature", [0.0], 0.0)
@test isapprox(T[1], 1.0)
# Set constant flux g=6 on boundary. Accurate solution is
# u(x,y) = x which equals T=1 on boundary.
# at time t=1.0 all loads should be on.
solver.time = 1.0
solver()
T = el2("temperature", [0.0], 1.0)
@test isapprox(T[1], 2.0)
empty!(problem)
assemble!(problem, 1.0)
A = full(problem.assembly.K)
b = full(problem.assembly.f)
@test isapprox(A[free_dofs, free_dofs] \ b[free_dofs], [2.0, 2.0])
end
function T_acc(x)