API

# API documentation

## Index

``````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]
``````
source
``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``````
source
``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``````
source
``````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``````
source
``````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]))
``````
source
``````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``````
source