mirror of
https://github.com/JuliaFEM/JuliaFEM.jl.git
synced 2026-09-27 12:16:56 +00:00
2d finite sliding autodiff version i think it works now
This commit is contained in:
@@ -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
|
||||
@@ -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
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user