updated contact codes

This commit is contained in:
Jukka Aho
2016-10-01 13:37:15 +03:00
parent 9b1cc3e134
commit c79b4d5514
11 changed files with 410 additions and 78 deletions
+1
View File
@@ -109,6 +109,7 @@ include("problems_contact.jl")
include("problems_contact_2d.jl")
include("problems_contact_3d.jl")
include("problems_contact_2d_autodiff.jl")
#include("problems_contact_3d_autodiff.jl")
export Contact
module Preprocess
+1 -1
View File
@@ -603,7 +603,7 @@ function process_output_request(model::Model, solver::Solver, output_request::Ab
results = join(results, tables[i], on=:ELEMENT, kind=:outer)
end
end
sort!(results, cols=[:ELEMENT, :IP])
#sort!(results; cols=[:ELEMENT, :IP])
# filter out elements with id -1, they are automatically created boundary elements
fel = find(results[:ELEMENT] .!= Symbol("E-1"))
results = results[fel, :]
+42 -17
View File
@@ -11,11 +11,11 @@ type Element{E<:AbstractElement}
properties :: E
end
function Element{E<:AbstractElement}(::Type{E}, id::Int64, connectivity::Vector{Int64})
function Element{E<:AbstractElement}(::Type{E}, id::Int64, connectivity=[])
return Element{E}(id, connectivity, [], Dict(), E())
end
function Element{E<:AbstractElement}(::Type{E}, connectivity::Vector{Int64})
function Element{E<:AbstractElement}(::Type{E}, connectivity=[])
return Element{E}(-1, connectivity, [], Dict(), E())
end
@@ -44,11 +44,11 @@ function setindex!(element::Element, data, field_name)
element.fields[field_name] = Field(data)
end
function call(element::Element, field_name)
function call(element::Element, field_name::AbstractString)
return element[field_name]
end
function call(element::Element, field_name, time)
function call(element::Element, field_name::AbstractString, time::Float64)
return element[field_name](time)
end
@@ -60,6 +60,31 @@ function call(element::Element, ip, time::Float64=0.0)
return get_basis(element, ip, time)
end
"""
Examples
julia> el = Element(Quad4, [1, 2, 3, 4]);
julia> el([0.0, 0.0], 0.0, 1)
1x4 Array{Float64,2}:
0.25 0.25 0.25 0.25
julia> el([0.0, 0.0], 0.0, 2)
2x8 Array{Float64,2}:
0.25 0.0 0.25 0.0 0.25 0.0 0.25 0.0
0.0 0.25 0.0 0.25 0.0 0.25 0.0 0.25
"""
function call(element::Element, ip, time::Float64, dim::Int)
dim == 1 && return get_basis(element, ip, time)
Ni = get_basis(element, ip, time)
N = zeros(dim, length(element)*dim)
for i=1:dim
N[i,i:dim:end] += Ni
end
return N
end
function call(element::Element, ip, time::Float64, ::Type{Val{:Jacobian}})
X = element("geometry", time)
dN = get_dbasis(element, ip, time)
@@ -96,15 +121,15 @@ function call(element::Element, field_name::AbstractString, ip, time::Float64, :
return element(ip, time, Val{:Grad})*element[field_name](time)
end
function call(element::Element, field::Field, time)
function call(element::Element, field::Field, time::Float64)
return field(time)
end
function call(element::Element, field::DCTI, time)
function call(element::Element, field::DCTI, time::Float64)
return field.data
end
function call(element::Element, field_name::AbstractString, time)
function call(element::Element, field_name::AbstractString, time::Float64)
field = element[field_name]
return element(field, time)
end
@@ -157,7 +182,7 @@ julia> update!(element, "geometry", data)
As a result element now have time invariant (variable) vector field "geometry" with data ([0.0, 0.0], [1.0, 2.0]).
"""
function update!(element::Element, field_name, data::Dict)
function update!(element::Element, field_name::AbstractString, data::Dict)
#element[field_name] = Field(data)
element[field_name] = [data[i] for i in get_connectivity(element)]
end
@@ -195,7 +220,7 @@ function update!(element::Element, field_name, data::Pair...)
end
=#
function update!(element::Element, field_name, data::Pair{Float64, Vector{Any}})
function update!(element::Element, field_name::AbstractString, data::Pair{Float64, Vector{Any}})
if haskey(element, field_name)
update!(element[field_name], data)
else
@@ -203,7 +228,7 @@ function update!(element::Element, field_name, data::Pair{Float64, Vector{Any}})
end
end
function update!(element::Element, field_name, data::Pair{Float64, Vector{Int64}})
function update!(element::Element, field_name::AbstractString, data::Pair{Float64, Vector{Int64}})
if haskey(element, field_name)
update!(element[field_name], data)
else
@@ -211,7 +236,7 @@ function update!(element::Element, field_name, data::Pair{Float64, Vector{Int64}
end
end
function update!(element::Element, field_name, data::Pair{Float64, Vector{Float64}})
function update!(element::Element, field_name::AbstractString, data::Pair{Float64, Vector{Float64}})
if haskey(element, field_name)
update!(element[field_name], data)
else
@@ -219,7 +244,7 @@ function update!(element::Element, field_name, data::Pair{Float64, Vector{Float6
end
end
function update!(element::Element, field_name, data::Pair{Float64, Vector{Vector{Float64}}})
function update!(element::Element, field_name::AbstractString, data::Pair{Float64, Vector{Vector{Float64}}})
if haskey(element, field_name)
update!(element[field_name], data)
else
@@ -227,7 +252,7 @@ function update!(element::Element, field_name, data::Pair{Float64, Vector{Vector
end
end
function update!(element::Element, field_name, data::Pair{Float64, Float64})
function update!(element::Element, field_name::AbstractString, data::Pair{Float64, Float64})
if haskey(element, field_name)
update!(element[field_name], data)
else
@@ -257,22 +282,22 @@ function update!(element::Element, datas::Pair...)
end
end
function update!(element::Element, field_name, data::Function)
function update!(element::Element, field_name::AbstractString, data::Function)
element[field_name] = data
end
function update!(element::Element, field_name, field::Field)
function update!(element::Element, field_name::AbstractString, field::Field)
element[field_name] = field
end
function update!(elements::Vector, field_name, data)
function update!(elements::Vector, field_name::AbstractString, data)
for element in elements
update!(element, field_name, data)
end
end
""" Check existence of field. """
function haskey(element::Element, field_name)
function haskey(element::Element, field_name::AbstractString)
haskey(element.fields, field_name)
end
+3
View File
@@ -677,3 +677,6 @@ function inside(::Union{Type{Tri3}, Type{Tri6}, Type{Tri7}, Type{Tet4}, Type{Tet
return all(xi .>= 0.0) && (sum(xi) <= 1.0)
end
function get_reference_coordinates{E}(element::Element{E})
get_reference_coordinates(E)
end
+2 -2
View File
@@ -166,13 +166,13 @@ function reorder_element_connectivity!(mesh::Mesh, mapping::Dict{Symbol, Vector{
end
function JuliaFEM.Problem{P<:FieldProblem}(mesh::Mesh, ::Type{P}, name::AbstractString, dimension::Int64)
problem = Problem{P}(name, dimension, "none", [], Dict(), Assembly(), P())
problem = Problem(P, name, dimension)
problem.elements = create_elements(mesh, name)
return problem
end
function JuliaFEM.Problem{P<:BoundaryProblem}(mesh::Mesh, ::Type{P}, name, dimension, parent_field_name)
problem = Problem{P}(name, dimension, parent_field_name, [], Dict(), Assembly(), P())
problem = Problem(P, name, dimension, parent_field_name)
problem.elements = create_elements(mesh, name)
return problem
end
+10 -10
View File
@@ -284,11 +284,11 @@ function length(problem::Problem)
end
function update!(problem::Problem, field_name::AbstractString, data)
if haskey(problem.fields, field_name)
update!(problem.fields[field_name], field_name::AbstractString, data)
else
problem.fields[field_name] = Field(data)
end
#if haskey(problem.fields, field_name)
# update!(problem.fields[field_name], field_name::AbstractString, data)
#else
# problem.fields[field_name] = Field(data)
#end
update!(problem.elements, field_name::AbstractString, data)
end
@@ -302,9 +302,9 @@ end
""" Return field calculated to nodal points for elements in problem p. """
function call(problem::Problem, field_name::AbstractString, time::Float64=0.0)
if haskey(problem, field_name)
return problem[field_name](time)
end
#if haskey(problem, field_name)
# return problem[field_name](time)
#end
f = nothing
for element in get_elements(problem)
haskey(element, field_name) || continue
@@ -323,8 +323,8 @@ function call(problem::Problem, field_name::AbstractString, time::Float64=0.0)
end
end
end
f == nothing && return f
update!(problem, field_name, time => f)
#f == nothing && return f
#update!(problem, field_name, time => f)
return f
end
+285 -15
View File
@@ -182,10 +182,10 @@ function assemble!(problem::Problem{Contact}, time::Float64,
la = problem.assembly.la
ndofs = length(la)
info("contact ndofs: $ndofs")
info("Rn = $Rn")
# info("contact ndofs: $ndofs")
# info("Rn = $Rn")
C1 = sparse(problem.assembly.C1)
C1 = sparse(problem.assembly.C1, ndofs, ndofs)
C2 = sparse(problem.assembly.C2, ndofs, ndofs)
D = sparse(problem.assembly.D, ndofs, ndofs)
g = full(problem.assembly.g, ndofs, 1)
@@ -216,11 +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")
# _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
@@ -246,12 +246,12 @@ function assemble!(problem::Problem{Contact}, time::Float64,
update!(slave_elements, "slip nodes", time => is_slip)
end
info("# | active | inactive | stick | slip | gap | pres | comp")
for j in S
str1 = "$j | $(is_active[j]) | $(is_inactive[j]) | $(is_stick[j]) | $(is_slip[j]) | "
str2 = "$(round(weighted_gap[j], 3)) | $(round(contact_pressure[j], 3)) | $(round(complementarity_condition[j], 3))"
info(str1 * str2)
end
# info("# | active | inactive | stick | slip | gap | pres | comp")
# for j in S
# str1 = "$j | $(is_active[j]) | $(is_inactive[j]) | $(is_stick[j]) | $(is_slip[j]) | "
# str2 = "$(round(weighted_gap[j], 3)) | $(round(contact_pressure[j], 3)) | $(round(complementarity_condition[j], 3))"
# info(str1 * str2)
# end
# solve variational inequality
@@ -273,7 +273,7 @@ function assemble!(problem::Problem{Contact}, time::Float64,
for j in S
dofs = [2*(j-1)+1, 2*(j-1)+2]
if is_inactive[j] == 1
info("$j is inactive, removing dofs $dofs")
# info("$j is inactive, removing dofs $dofs")
C1[dofs,:] = 0.0
C2[dofs,:] = 0.0
D[dofs,:] = 0.0
@@ -287,3 +287,273 @@ function assemble!(problem::Problem{Contact}, time::Float64,
problem.assembly.g = g
end
"""
Frictionless 2d small sliding contact without forwarddiff.
true/false flags: finite_sliding, friction, use_forwarddiff
"""
function _assemble!(problem::Problem{Contact}, time::Float64,
::Type{Val{1}}, ::Type{Val{false}},
::Type{Val{false}}, ::Type{Val{false}}; debug=false)
props = problem.properties
field_dim = get_unknown_field_dimension(problem)
field_name = get_parent_field_name(problem)
slave_elements = get_slave_elements(problem)
# 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", time => normals)
update!(slave_elements, "tangent", time => tangents)
Rn = 0.0
# 2. loop all slave elements
for slave_element in slave_elements
nsl = length(slave_element)
X1 = slave_element("geometry", time)
u1 = slave_element("displacement", time)
la1 = slave_element("reaction force", time)
n1 = slave_element("normal", time)
t1 = slave_element("tangent", time)
x1 = X1 + u1
Q1_ = [n1[1] t1[1]]
Q2_ = [n1[2] t1[2]]
Z = zeros(2, 2)
Q2 = [Q1_ Z; Z Q2_]
contact_area = 0.0
contact_error = 0.0
if "element area" in props.store_fields
element_area = 0.0
for ip in get_integration_points(slave_element)
detJ = slave_element(ip, time, Val{:detJ})
w = ip.weight*detJ
element_area += w
end
update!(slave_element, "element area", time => element_area)
end
# 3. loop all master elements
for master_element in slave_element("master elements", time)
nm = length(master_element)
X2 = master_element("geometry", time)
u2 = master_element("displacement", time)
x2 = X2 + u2
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)
xi1b = project_from_master_to_slave(slave_element, X2[2], time)
xi1 = clamp([xi1a; xi1b], -1.0, 1.0)
l = 1/2*abs(xi1[2]-xi1[1])
isapprox(l, 0.0) && continue # no contribution in this master element
# 3.2. bi-orthogonal basis
De = zeros(nsl, nsl)
Me = zeros(nsl, nsl)
Ae = zeros(nsl, nsl)
if props.dual_basis
for ip in get_integration_points(slave_element, 3)
detJ = slave_element(ip, time, Val{:detJ})
w = ip.weight*detJ*l
xi = ip.coords[1]
xi_s = dot([1/2*(1-xi); 1/2*(1+xi)], xi1)
N1 = vec(get_basis(slave_element, xi_s, time))
De += w*diagm(N1)
Me += w*N1*N1'
end
Ae = De*inv(Me)
else
Ae = eye(nsl)
end
# 3.3. loop integration points of one integration segment and calculate
# local mortar matrices
fill!(De, 0.0)
fill!(Me, 0.0)
ge = zeros(field_dim*nsl)
for ip in get_integration_points(slave_element, 3)
detJ = slave_element(ip, time, Val{:detJ})
w = ip.weight*detJ*l
xi = ip.coords[1]
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
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_area += w
contact_error += 1/2*w*dot(n_s, x_s-x_m)^2
end
sdofs = get_gdofs(problem, slave_element)
mdofs = get_gdofs(problem, master_element)
# add contribution to contact virtual work
D2 = zeros(field_dim*nsl, field_dim*nsl)
M2 = zeros(field_dim*nsl, field_dim*nsl)
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
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)
ge = -D2*vec(x1)+M2*vec(x2)
add!(problem.assembly.g, sdofs, Q2'*ge)
ce = vec(la1) + ge
add!(problem.assembly.c, sdofs, Q2'*ce)
end # master elements done
if "contact area" in props.store_fields
update!(slave_element, "contact area", time => contact_area)
end
if "contact error" in props.store_fields
update!(slave_element, "contact error", time => contact_error)
end
end # slave elements done, contact virtual work ready
S = sort(collect(keys(normals))) # slave element nodes
weighted_gap = Dict{Int64, Vector{Float64}}()
contact_pressure = Dict{Int64, Vector{Float64}}()
complementarity_condition = Dict{Int64, Vector{Float64}}()
is_active = Dict{Int64, Int}()
is_inactive = Dict{Int64, Int}()
is_slip = Dict{Int64, Int}()
is_stick = Dict{Int64, Int}()
la = problem.assembly.la
ndofs = length(la)
C1 = sparse(problem.assembly.C1)
C2 = sparse(problem.assembly.C2, ndofs, ndofs)
D = spzeros(ndofs, ndofs)
c = full(problem.assembly.c, ndofs, 1)
g = full(problem.assembly.g, 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])
contact_pressure[j] = [p, t]
else
contact_pressure[j] = [0.0, 0.0]
end
#complementarity_condition[j] = contact_pressure[j] - weighted_gap[j]
complementarity_condition[j] = c[dofs]
if complementarity_condition[j][1] < 0
is_inactive[j] = 1
is_active[j] = 0
is_slip[j] = 0
is_stick[j] = 0
else
is_inactive[j] = 0
is_active[j] = 1
is_slip[j] = 1
is_stick[j] = 0
end
end
if "weighted gap" in props.store_fields
update!(slave_elements, "weighted gap", time => weighted_gap)
end
if "contact pressure" in props.store_fields
update!(slave_elements, "contact pressure", time => contact_pressure)
end
if "complementarity condition" in props.store_fields
update!(slave_elements, "complementarity condition", time => complementarity_condition)
end
if "active nodes" in props.store_fields
update!(slave_elements, "active nodes", time => is_active)
end
if "inactive nodes" in props.store_fields
update!(slave_elements, "inactive nodes", time => is_inactive)
end
if "stick nodes" in props.store_fields
update!(slave_elements, "stick nodes", time => is_stick)
end
if "slip nodes" in props.store_fields
update!(slave_elements, "slip nodes", time => is_slip)
end
# info("# | active | inactive | stick | slip | gap | pres | comp")
# for j in S
# str1 = "$j | $(is_active[j]) | $(is_inactive[j]) | $(is_stick[j]) | $(is_slip[j]) | "
# str2 = "$(round(weighted_gap[j], 3)) | $(round(contact_pressure[j], 3)) | $(round(complementarity_condition[j], 3))"
# info(str1 * str2)
# end
# solve variational inequality
# 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)
# info("$j is in active/slip, removing tangential constraint $(dofs[2])")
C2[dofs[2],:] = 0.0
g[dofs[2]] = 0.0
D[dofs[2], dofs] = tangents[j]
end
end
# remove inactive nodes from assembly
for j in S
dofs = [2*(j-1)+1, 2*(j-1)+2]
if is_inactive[j] == 1
# info("$j is inactive, removing dofs $dofs")
C1[dofs,:] = 0.0
C2[dofs,:] = 0.0
D[dofs,:] = 0.0
g[dofs,:] = 0.0
end
end
problem.assembly.C1 = C1
problem.assembly.C2 = C2
problem.assembly.D = D
problem.assembly.g = g
end
+9
View File
@@ -121,12 +121,21 @@ function assemble!(problem::Problem{Contact}, time::Float64,
X_el = element("geometry", time)
u_el = Field(Vector[u[:,i] for i in conn])
x_el = X_el + u_el
#=
for ip in get_integration_points(element, 3)
dN = get_dbasis(element, ip, time)
N = element(ip, time)
t = sum([kron(dN[:,i], x_el[i]') for i=1:length(x_el)])
normals[:, conn] += ip.weight*Q*t'*N
end
=#
dN = get_dbasis(element, [0.0], time)
t = sum([kron(dN[:,i], x_el[i]') for i=1:length(x_el)])
n = Q*t'
n /= norm(n)
for c in conn
normals[:,c] += n
end
end
for i in 1:size(normals,2)
normals[:,i] /= norm(normals[:,i])
+47 -25
View File
@@ -12,7 +12,7 @@ function create_orthogonal_basis(n)
end
"""
Frictionless 2d small sliding contact.
Frictionless 3d small sliding contact.
problem
time
@@ -33,7 +33,7 @@ function assemble!(problem::Problem{Contact}, time::Float64,
# 1. calculate nodal normals and tangents for slave element nodes j ∈ S
normals = calculate_normals(slave_elements, time, Val{2};
rotate_normals=props.rotate_normals)
update!(slave_elements, "normal", normals)
update!(slave_elements, "normal", time => normals)
# 2. loop all slave elements
for (slave_num, slave_element) in enumerate(slave_elements)
@@ -43,14 +43,29 @@ function assemble!(problem::Problem{Contact}, time::Float64,
u1 = slave_element("displacement", time)
la = slave_element("reaction force", time)
n1 = slave_element("normal", time)
t11, t21 = create_orthogonal_basis(n1[1])
t12, t22 = create_orthogonal_basis(n1[2])
t13, t23 = create_orthogonal_basis(n1[3])
Q1_ = [n1[1] t11 t21]
Q2_ = [n1[2] t12 t22]
Q3_ = [n1[3] t13 t23]
Z = zeros(3, 3)
Q3 = [Q1_ Z Z; Z Q2_ Z; Z Z Q3_]
if nsl == 3
t11, t21 = create_orthogonal_basis(n1[1])
t12, t22 = create_orthogonal_basis(n1[2])
t13, t23 = create_orthogonal_basis(n1[3])
Q1_ = [n1[1] t11 t21]
Q2_ = [n1[2] t12 t22]
Q3_ = [n1[3] t13 t23]
Z = zeros(3, 3)
Q3 = [Q1_ Z Z; Z Q2_ Z; Z Z Q3_]
elseif nsl == 4
t11, t21 = create_orthogonal_basis(n1[1])
t12, t22 = create_orthogonal_basis(n1[2])
t13, t23 = create_orthogonal_basis(n1[3])
t14, t24 = create_orthogonal_basis(n1[4])
Q1_ = [n1[1] t11 t21]
Q2_ = [n1[2] t12 t22]
Q3_ = [n1[3] t13 t23]
Q4_ = [n1[4] t14 t24]
Z = zeros(3, 3)
Q3 = [Q1_ Z Z Z; Z Q2_ Z Z; Z Z Q3_ Z; Z Z Z Q4_]
else
error("nsl = $nsl")
end
contact_area = 0.0
contact_error = 0.0
@@ -64,15 +79,19 @@ function assemble!(problem::Problem{Contact}, time::Float64,
update!(slave_element, "element area", time => element_area)
end
if slave_num == 1
info("First slave element area = $element_area")
info("NT basis of first slave element")
dump(Q3)
end
# if slave_num == 1
# info("First slave element area = $element_area")
# info("NT basis of first slave element")
# dump(Q3)
# end
# project slave nodes to auxiliary plane (x0, Q)
#xi = get_reference_element_midpoint(slave_element)
xi = [1/3, 1/3]
if nsl == 3
xi = [1/3, 1/3]
else
xi = [1/4, 1/4]
end
N = vec(get_basis(slave_element, xi, time))
x0 = N*X1
n0 = N*n1
@@ -151,7 +170,7 @@ function assemble!(problem::Problem{Contact}, time::Float64,
nsldofs = length(sdofs)
nmdofs = length(mdofs)
D3 = zeros(nsldofs, nsldofs)
M3 = zeros(nmdofs, nmdofs)
M3 = zeros(nsldofs, nmdofs)
for i=1:field_dim
D3[i:field_dim:end, i:field_dim:end] += De
M3[i:field_dim:end, i:field_dim:end] += Me
@@ -180,8 +199,14 @@ 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)
C1 = sparse(problem.assembly.C1, ndofs, ndofs)
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
@@ -233,26 +258,23 @@ function assemble!(problem::Problem{Contact}, time::Float64,
update!(slave_elements, "slip nodes", time => is_slip)
end
#=
info("# | active | inactive | stick | slip | gap | pres | comp")
for j in S
str1 = "$j | $(is_active[j]) | $(is_inactive[j]) | $(is_stick[j]) | $(is_slip[j]) | "
str2 = "$(round(weighted_gap[j], 3)) | $(round(contact_pressure[j], 3)) | $(round(complementarity_condition[j], 3))"
info(str1 * str2)
end
=#
# 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 = [3*(j-1)+1, 3*(j-1)+2, 3*(j-1)+3]
tdofs = dofs[[2,3]]
if (is_active[j] == 1) && (is_slip[j] == 1)
info("$j is in active/slip, removing tangential constraints $tdofs")
# info("$j is in active/slip, removing tangential constraints $tdofs")
C2[tdofs,:] = 0.0
g[tdofs] = 0.0
normal = normals[j]
@@ -266,7 +288,7 @@ function assemble!(problem::Problem{Contact}, time::Float64,
for j in S
dofs = [3*(j-1)+1, 3*(j-1)+2, 3*(j-1)+3]
if is_inactive[j] == 1
info("$j is inactive, removing dofs $dofs")
# info("$j is inactive, removing dofs $dofs")
C1[dofs,:] = 0.0
C2[dofs,:] = 0.0
D[dofs,:] = 0.0
+1 -1
View File
@@ -105,7 +105,7 @@ function get_polygon_clip(xs, xm, n; debug=false)
# objective: search does line xm1 - xm2 clip xs
nm = length(xm)
ns = length(xs)
P = Vector{Float64}[]
P = Vector{Number}[]
# 1. test is master point inside slave, if yes, add to clip
for i=1:nm
@@ -75,9 +75,11 @@ using JuliaFEM.Testing
# element details
el = first(block.elements)
X = el("geometry", 0.0)
debug("X = $X")
S1 = block(el, [0.0, 0.0], 0.0, Val{:S})
S1 = S1[[1,4,2]]
E1= block(el, [0.0, 0.0], 0.0, Val{:E})
E1 = block(el, [0.0, 0.0], 0.0, Val{:E})
E1 = E1[[1,4,2]]
C1 = block(el, [0.0, 0.0], 0.0, Val{:COORD})
info("strain = $E1, stress = $S1, at $C1")
@@ -103,12 +105,12 @@ using JuliaFEM.Testing
info("u3 = $u")
@test isapprox(u, u3_expected)
info("calling nonlinear solver")
solver2 = NonlinearSolver(block, traction, bc_sym_23, bc_sym_13)
solver2()
u = solver2("displacement", 0.0)[3]
info("nlsolver u3 = $u, expected = $u3_expected")
@test isapprox(u, u3_expected; rtol=1.0e-5)
# info("calling nonlinear solver")
# solver2 = NonlinearSolver(block, traction, bc_sym_23, bc_sym_13)
# solver2()
# u = solver2("displacement", 0.0)[3]
# info("nlsolver u3 = $u, expected = $u3_expected")
# @test isapprox(u, u3_expected; rtol=1.0e-5)
end
#= TODO: to other file