minor changes to 2d contact formulation

This commit is contained in:
Jukka Aho
2016-09-12 03:39:33 +03:00
parent 45f605bfc7
commit 9b1cc3e134
5 changed files with 127 additions and 39 deletions
+10 -10
View File
@@ -158,19 +158,19 @@ As a result element now have time invariant (variable) vector field "geometry" w
"""
function update!(element::Element, field_name, data::Dict)
element[field_name] = Field(data)
#element[field_name] = [data[i] for i in get_connectivity(element)]
#element[field_name] = Field(data)
element[field_name] = [data[i] for i in get_connectivity(element)]
end
function update!{K,V}(element::Element, field_name, data::Pair{Float64, Dict{K, V}})
#time, field_data = data
#element_data = V[field_data[i] for i in get_connectivity(element)]
#update!(element, field_name, time => element_data)
if haskey(element, field_name)
update!(element[field_name], data)
else
element[field_name] = Field(data)
end
time, field_data = data
element_data = V[field_data[i] for i in get_connectivity(element)]
update!(element, field_name, time => element_data)
#if haskey(element, field_name)
# update!(element[field_name], data)
#else
# element[field_name] = Field(data)
#end
end
function update!(element::Element, field_name::AbstractString, datas::Union{Real, Vector, Pair{Float64, Union{Float64, Real, Vector{Any}}}}...)
+2 -1
View File
@@ -19,6 +19,7 @@ type Contact <: BoundaryProblem
use_forwarddiff :: Bool
minimum_active_set_size :: Int
distval :: Float64
remove_from_set :: Bool # allow removal of non-potential contact pairs
store_fields :: Vector{AbstractString}
end
@@ -26,7 +27,7 @@ function Contact()
default_fields = ["element area", "contact area", "weighted gap",
"contact pressure", "active nodes", "inactive nodes", "stick nodes",
"slip nodes", "complementarity condition", "contact error"]
return Contact(-1, false, false, false, true, false, 0, 5.0, default_fields)
return Contact(-1, false, false, false, true, false, 0, 5.0, false, default_fields)
end
function get_unknown_field_name(problem::Problem{Contact})
+64 -23
View File
@@ -21,6 +21,8 @@ function assemble!(problem::Problem{Contact}, time::Float64,
update!(slave_elements, "normal", time => normals)
update!(slave_elements, "tangent", time => tangents)
Rn = 0.0
# 2. loop all slave elements
for slave_element in slave_elements
@@ -56,8 +58,13 @@ function assemble!(problem::Problem{Contact}, time::Float64,
u2 = master_element("displacement", time)
x2 = X2 + u2
norm(mean(X1) - X2[1]) / norm(X1[2] - X1[1]) < props.distval || continue
norm(mean(X1) - X2[2]) / norm(X1[2] - X1[1]) < props.distval || continue
if norm(mean(X1) - X2[1]) / norm(X1[2] - X1[1]) > props.distval
continue
end
if norm(mean(X1) - X2[2]) / norm(X1[2] - X1[1]) > props.distval
continue
end
# 3.1 calculate segmentation
xi1a = project_from_master_to_slave(slave_element, X2[1], time)
@@ -89,7 +96,11 @@ function assemble!(problem::Problem{Contact}, time::Float64,
# local mortar matrices
fill!(De, 0.0)
fill!(Me, 0.0)
ge = zeros(field_dim*nsl)
Ne = zeros(nsl, 2*nsl)
Te = zeros(nsl, 2*nsl)
He = zeros(nsl, 2*nsl)
ce = zeros(nsl)
ge = zeros(nsl)
for ip in get_integration_points(slave_element, 3)
detJ = slave_element(ip, time, Val{:detJ})
w = ip.weight*detJ*l
@@ -97,40 +108,56 @@ function assemble!(problem::Problem{Contact}, time::Float64,
xi_s = dot([1/2*(1-xi); 1/2*(1+xi)], xi1)
N1 = vec(get_basis(slave_element, xi_s, time))
Phi = Ae*N1
# project gauss point from slave element to master element in direction n_s
X_s = N1*X1 # coordinate in gauss point
n_s = N1*n1 # normal direction in gauss point
t_s = N1*t1 # tangent condition in gauss point
n_s /= norm(n_s)
t_s /= norm(t_s)
xi_m = project_from_slave_to_master(master_element, X_s, n_s, time)
N2 = vec(get_basis(master_element, xi_m, time))
X_m = N2*X2
De += w*Phi*N1'
Me += w*Phi*N2'
u_s = N1*u1
u_m = N2*u2
x_s = X_s + u_s
x_m = X_m + u_m
la_s = Phi*la1
ge += w*vec((x_m-x_s)*Phi')
# virtual work
De += w*Phi*N1'
Me += w*Phi*N2'
# contact constraints
Ne += w*reshape(kron(N1, n_s, Phi), 2, 4)
Te += w*reshape(kron(N2, n_s, Phi), 2, 4)
He += w*reshape(kron(N1, t_s, Phi), 2, 4)
ge += w*Phi*dot(n_s, x_m-x_s)
ce += w*N1*dot(n_s, -la_s)
Rn += w*dot(n_s, -la_s)
contact_area += w
contact_error += 1/2*w*dot(n_s, x_s-x_m)^2
end
# add contribution to contact virtual work
sdofs = get_gdofs(problem, slave_element)
mdofs = get_gdofs(problem, master_element)
nsldofs = length(sdofs)
nmdofs = length(mdofs)
D2 = zeros(nsldofs, nsldofs)
M2 = zeros(nmdofs, nmdofs)
# add contribution to contact virtual work
for i=1:field_dim
D2[i:field_dim:end, i:field_dim:end] += De
M2[i:field_dim:end, i:field_dim:end] += Me
lsdofs = sdofs[i:field_dim:end]
lmdofs = mdofs[i:field_dim:end]
add!(problem.assembly.C1, lsdofs, lsdofs, De)
add!(problem.assembly.C1, lsdofs, lmdofs, -Me)
end
add!(problem.assembly.C1, sdofs, sdofs, D2)
add!(problem.assembly.C1, sdofs, mdofs, -M2)
add!(problem.assembly.C2, sdofs, sdofs, Q2'*D2)
add!(problem.assembly.C2, sdofs, mdofs, -Q2'*M2)
add!(problem.assembly.g, sdofs, Q2'*ge)
# add contribution to contact constraints
add!(problem.assembly.C2, sdofs[1:field_dim:end], sdofs, Ne)
add!(problem.assembly.C2, sdofs[1:field_dim:end], mdofs, -Te)
add!(problem.assembly.D, sdofs[2:field_dim:end], sdofs, He)
add!(problem.assembly.g, sdofs[1:field_dim:end], ge)
add!(problem.assembly.c, sdofs[1:field_dim:end], ce)
end # master elements done
@@ -153,13 +180,22 @@ function assemble!(problem::Problem{Contact}, time::Float64,
is_slip = Dict{Int64, Int}()
is_stick = Dict{Int64, Int}()
g = full(problem.assembly.g)
la = problem.assembly.la
ndofs = length(la)
info("contact ndofs: $ndofs")
info("Rn = $Rn")
C1 = sparse(problem.assembly.C1)
C2 = sparse(problem.assembly.C2, ndofs, ndofs)
D = sparse(problem.assembly.D, ndofs, ndofs)
g = full(problem.assembly.g, ndofs, 1)
c = full(problem.assembly.c, ndofs, 1)
# active / inactive node detection
for j in S
dofs = [2*(j-1)+1, 2*(j-1)+2]
weighted_gap[j] = g[dofs]
if length(la) != 0
p = dot(normals[j], la[dofs])
t = dot(tangents[j], la[dofs])
@@ -167,6 +203,8 @@ function assemble!(problem::Problem{Contact}, time::Float64,
else
contact_pressure[j] = [0.0, 0.0]
end
# contact_pressure[j] = c[dofs]
complementarity_condition[j] = contact_pressure[j] - weighted_gap[j]
if complementarity_condition[j][1] < 0
is_inactive[j] = 1
@@ -178,6 +216,11 @@ function assemble!(problem::Problem{Contact}, time::Float64,
is_active[j] = 1
is_slip[j] = 1
is_stick[j] = 0
_c1 = complementarity_condition[j][1]
_c2 = c[dofs]
_c3 = contact_pressure[j][1]
_c4 = g[dofs]
info("active $j: c1 = $_c1, c2 = $_c2, c3 = $_c3, c4 = $_c4")
end
end
@@ -212,12 +255,9 @@ function assemble!(problem::Problem{Contact}, time::Float64,
# solve variational inequality
C1 = sparse(problem.assembly.C1)
ndofs = size(C1, 1)
C2 = sparse(problem.assembly.C2)
D = spzeros(ndofs, ndofs)
# constitutive modelling in tangent direction, frictionless contact
#=
for j in S
dofs = [2*(j-1)+1, 2*(j-1)+2]
if (is_active[j] == 1) && (is_slip[j] == 1)
@@ -227,6 +267,7 @@ function assemble!(problem::Problem{Contact}, time::Float64,
D[dofs[2], dofs] = tangents[j]
end
end
=#
# remove inactive nodes from assembly
for j in S
+6 -5
View File
@@ -68,9 +68,10 @@ function calculate_normals(elements, time, ::Type{Val{1}}; rotate_normals=false)
tangents = Dict{Int64, Vector{Float64}}()
for element in elements
conn = get_connectivity(element)
X1 = element("geometry", time)
dN = get_dbasis(element, [0.0], time)
tangent = vec(sum([kron(dN[:,i], X1[i]') for i=1:length(X1)]))
#X1 = element("geometry", time)
#dN = get_dbasis(element, [0.0], time)
#tangent = vec(sum([kron(dN[:,i], X1[i]') for i=1:length(X1)]))
tangent = vec(element([0.0], time, Val{:Jacobian}))
for nid in conn
if haskey(tangents, nid)
tangents[nid] += tangent
@@ -116,8 +117,8 @@ function assemble!(problem::Problem{Mortar}, time::Float64, ::Type{Val{1}}, ::Ty
# 1. calculate nodal normals and tangents for slave element nodes j ∈ S
normals, tangents = calculate_normals(slave_elements, time, Val{1};
rotate_normals=props.rotate_normals)
update!(slave_elements, "normal", normals)
update!(slave_elements, "tangent", tangents)
update!(slave_elements, "normal", time => normals)
update!(slave_elements, "tangent", time => tangents)
# 2. loop all slave elements
for slave_element in slave_elements
+45
View File
@@ -0,0 +1,45 @@
# 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
@testset "test 2d linear elasticity with surface + volume load" begin
meshfile = "/geometry/2d_block/BLOCK_1elem.med"
mesh = aster_read_mesh(Pkg.dir("JuliaFEM")*meshfile)
# field problem
block = Problem(Elasticity, "BLOCK", 2)
block.properties.formulation = :plane_strain
block.properties.finite_strain = false
block.properties.geometric_stiffness = false
block.elements = create_elements(mesh, "BLOCK")
update!(block.elements, "youngs modulus", 288.0)
update!(block.elements, "poissons ratio", 1/3)
# traction
traction = Problem(Elasticity, "TRACTION", 2)
traction.properties.formulation = :plane_strain
traction.properties.finite_strain = false
traction.properties.geometric_stiffness = false
traction.elements = create_elements(mesh, "TOP")
update!(traction, "displacement traction force 2", 288.0*9/8)
# boundary conditions
bc_sym_23 = Problem(Dirichlet, "symmetry bc 23", 2, "displacement")
bc_sym_23.elements = create_elements(mesh, "LEFT")
update!(bc_sym_23, "displacement 1", 0.0)
bc_sym_13 = Problem(Dirichlet, "symmetry bc 13", 2, "displacement")
bc_sym_13.elements = create_elements(mesh, "BOTTOM")
update!(bc_sym_13, "displacement 2", 0.0)
solver = LinearSolver(block, traction, bc_sym_23, bc_sym_13)
solver()
info("u = ", block.assembly.u)
info("λ = ", block.assembly.la)
end