API documentation
Index
Mortar2D.calculate_mortar_assembly
Mortar2D.calculate_mortar_matrices
Mortar2D.calculate_normals
Mortar2D.calculate_segments
Mortar2D.project_from_master_to_slave
Mortar2D.project_from_slave_to_master
Mortar2D.calculate_normals
— Function.calculate_normals(elements::Dict{Int, Vector{Int}},
element_types::Dict{Int, Symbol},
X::Dict{Int, Vector{Float64})
Given elements, element types and node locations, calculate nodal normals by first calculating normal directions for each element and then averaging them in nodes. As a result we get unique normal direction defined to each node.
Notes
Only linear elements supported.
Example
X = Dict(1 => [7.0, 7.0], 2 => [4.0, 3.0], 3 => [0.0, 0.0])
elements = Dict(1 => [1, 2], 2 => [2, 3])
element_types = Dict(1 => :Seg2, 2 => :Seg2)
normals = calculate_normals(elements, element_types, X)
# output
Dict{Int64,Array{Float64,1}} with 3 entries:
2 => [0.707107, -0.707107]
3 => [0.6, -0.8]
1 => [0.8, -0.6]
Mortar2D.project_from_master_to_slave
— Function.project_from_master_to_slave(Val{:Seg2}, xm, xs1, xs2, ns1, ns2)
Find the projection of a master node xm
, to the slave surface with nodes (xs1
, xs2
), in direction of slave surface normal defined by (ns1
, ns2
). Returns slave element dimensionless parameter, that is, to find coordinates in slave side:
xs = 1/2*(1-xi)*xs1 + 1/2*(1+xi)*xs2
Example
xm = [4.0, -2.0]
xs1 = [0.0, 0.0]
xs2 = [4.0, 3.0]
ns1 = [3.0/5.0, -4.0/5.0]
ns2 = sqrt(2)/2*[1, -1]
xi1 = project_from_master_to_slave(Val{:Seg2}, xm, xs1, xs2, ns1, ns2)
round(xi1, digits=6)
# output
-0.281575
Mortar2D.project_from_slave_to_master
— Function.project_from_slave_to_master(Val{:Seg2}, xs, ns, xm1, xm2)
Find the projection of a slave node xs
, having normal vector ns
, onto master elements with nodes (xm1
, xm2
). Returns master element dimensionless parameter xi, that is,
xm = 1/2*(1-xi)*xm1 + 1/2*(1+xi)*xm2
Example
xm1 = [7.0, 2.0]
xm2 = [4.0, -2.0]
xs = [0.0, 0.0]
ns = [3.0/5.0, -4.0/5.0]
xi2 = project_from_slave_to_master(Val{:Seg2}, xs, ns, xm1, xm2)
round(xi2, digits=6)
# output
1.833333
Mortar2D.calculate_segments
— Function.calculate_segments(slave_element_ids::Vector{Int},
master_element_ids::Vector{Int},
elements::Dict{Int, Vector{Int}},
element_types::Dict{Int, Symbol},
coords::Dict{Int, Vector{Float64}},
normals::Dict{Int, Vector{Float64}})
Given slave surface elements, master surface elements, nodal coordinates and normal direction on nodes of slave surface elements, calculate contact segments.
Return type is a dictionary, where key is slave element id and values is a list of master elements giving contribution to that slave elements and xi-coordinates of slave side element.
Example
elements = Dict(1 => [1, 2], 2 => [3, 4])
element_types = Dict(1 => :Seg2, 2 => :Seg2)
coords = Dict(
1 => [1.0, 2.0],
2 => [3.0, 2.0],
3 => [0.0, 2.0],
4 => [2.0, 2.0])
normals = Dict(
1 => [0.0, -1.0],
2 => [0.0, -1.0])
slave_ids = [1]
master_ids = [2]
segments = calculate_segments(slave_ids, master_ids, elements,
element_types, coords, normals)
# output
Dict{Int64,Array{Tuple{Int64,Array{Float64,1}},1}} with 1 entry:
1 => Tuple{Int64,Array{Float64,1}}[(2, [-1.0, -0.0])]
Here, output result means that slave element #1 has segment with master element(s) #2 with dimensionless slave element coordinate xi = [-1, 0]. That is, the start and end point of projection in physical coordinate system is:
x_start = 1/2*(1-xi[1])*xs1 + 1/2*(1+xi[1])*xs2
x_stop = 1/2*(1-xi[2])*xs1 + 1/2*(1+xi[2])*xs2
Mortar2D.calculate_mortar_matrices
— Function.calculate_mortar_matrices(slave_element_id::Int,
elements::Dict{Int, Vector{Int}},
element_types::Dict{Int, Symbol},
coords::Dict{Int, Vector{Float64}},
normals::Dict{Int, Vector{Float64}},
segmentation:MortarSegmentation)
Calculate mortar matrices De and Me for slave element.
Example
elements = Dict(
1 => [1, 2],
2 => [3, 4])
element_types = Dict(
1 => :Seg2,
2 => :Seg2)
coords = Dict(
1 => [1.0, 2.0],
2 => [3.0, 2.0],
3 => [2.0, 2.0],
4 => [0.0, 2.0])
normals = Dict(
1 => [0.0, -1.0],
2 => [0.0, -1.0])
segmentation = Dict(1 => [(2, [-1.0, 0.0])])
De, Me = calculate_mortar_matrices(1, elements, element_types,
coords, normals, segmentation)
# output
([0.583333 0.166667; 0.166667 0.0833333], Dict(2=>[0.541667 0.208333; 0.208333 0.0416667]))
Mortar2D.calculate_mortar_assembly
— Function.calculate_mortar_assembly(elements::Dict{Int, Vector{Int}},
element_types::Dict{Int, Symbol},
coords::Dict{Int, Vector{Float64}},
slave_element_ids::Vector{Int},
master_element_ids::Vector{Int})
Given data, calculate projection matrices D
and M
. This is the main function of package. Relation between matrices is $D u_s = M u_m$, where $u_s$ is slave nodes and $u_m$ master nodes.
Example
Calculate mortar matrices for simple problem in README.md
Xs = Dict(1 => [0.0, 1.0], 2 => [5/4, 1.0], 3 => [2.0, 1.0])
Xm = Dict(4 => [0.0, 1.0], 5 => [1.0, 1.0], 6 => [2.0, 1.0])
coords = merge(Xm , Xs)
Es = Dict(1 => [1, 2], 2 => [2, 3])
Em = Dict(3 => [4, 5], 4 => [5, 6])
elements = merge(Es, Em)
element_types = Dict(1 => :Seg2, 2 => :Seg2, 3 => :Seg2, 4 => :Seg2)
slave_element_ids = [1, 2]
master_element_ids = [3, 4]
s, m, D, M = calculate_mortar_assembly(elements, element_types, coords,
slave_element_ids, master_element_ids)
# output
([1, 2, 3], [4, 5, 6],
[1, 1] = 0.416667
[2, 1] = 0.208333
[1, 2] = 0.208333
[2, 2] = 0.666667
[3, 2] = 0.125
[2, 3] = 0.125
[3, 3] = 0.25,
[1, 4] = 0.366667
[2, 4] = 0.133333
[1, 5] = 0.25625
[2, 5] = 0.65
[3, 5] = 0.09375
[1, 6] = 0.00208333
[2, 6] = 0.216667
[3, 6] = 0.28125)
s
and m
contains slave and master dofs:
julia> s, m
([1, 2, 3], [4, 5, 6])
D
is slave side mortar matrix:
julia> full(D[s,s])
3×3 Array{Float64,2}:
0.416667 0.208333 0.0
0.208333 0.666667 0.125
0.0 0.125 0.25
M
is master side mortar matrix:
julia> full(M[s,m])
3×3 Array{Float64,2}:
0.366667 0.25625 0.00208333
0.133333 0.65 0.216667
0.0 0.09375 0.28125