Skip to content

Commit 9134b54

Browse files
authored
Introduce isconstrained bitvector in ConstraintHandler (#1310)
* Introduce isconstrained bitvector in ch to speed up zero_out_rows Also used to make close simpler and slightly faster, and make it easier to check if dof is constrained
1 parent 8eb6a07 commit 9134b54

2 files changed

Lines changed: 29 additions & 25 deletions

File tree

ext/FerriteSparseMatrixCSR.jl

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,10 +67,11 @@ function Ferrite.zero_out_rows!(K::SparseMatrixCSR, ch::ConstraintHandler)
6767
end
6868

6969
function Ferrite.zero_out_columns!(K::SparseMatrixCSR, ch::ConstraintHandler)
70+
@boundscheck checkbounds(ch.isconstrained, axes(K, 2))
7071
colval = K.colval
7172
nzval = K.nzval
72-
return @inbounds for i in eachindex(colval, nzval)
73-
if haskey(ch.dofmapping, colval[i])
73+
return @inbounds for (i, col) in pairs(colval)
74+
if ch.isconstrained[col]
7475
nzval[i] = 0
7576
end
7677
end

src/Dofs/ConstraintHandler.jl

Lines changed: 26 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,7 @@ mutable struct ConstraintHandler{DH <: AbstractDofHandler, T}
166166
const dofcoefficients::Vector{Union{Nothing, DofCoefficients{T}}}
167167
# global dof -> index into dofs and inhomogeneities and dofcoefficients
168168
const dofmapping::Dict{Int, Int}
169+
const isconstrained::BitVector # Fast check if dof is constrained or not
169170
const bcvalues::Vector{BCValues{T}}
170171
const dh::DH
171172
closed::Bool
@@ -177,7 +178,7 @@ function ConstraintHandler(::Type{T}, dh::AbstractDofHandler) where {T <: Number
177178
@assert isclosed(dh)
178179
return ConstraintHandler(
179180
Dirichlet[], ProjectedDirichlet[], Int[], Int[], T[], Union{Nothing, T}[],
180-
Union{Nothing, DofCoefficients{T}}[], Dict{Int, Int}(), BCValues{T}[], dh, false,
181+
Union{Nothing, DofCoefficients{T}}[], Dict{Int, Int}(), BitVector(), BCValues{T}[], dh, false,
181182
)
182183
end
183184

@@ -259,21 +260,15 @@ isclosed(ch::ConstraintHandler) = ch.closed
259260
free_dofs(ch::ConstraintHandler) = ch.free_dofs
260261
prescribed_dofs(ch::ConstraintHandler) = ch.prescribed_dofs
261262

262-
# Equivalent to `copy!(out, setdiff(1:n_entries, diff))`, but requires that
263-
# `issorted(diff)` and that `1 ≤ diff[1] ≤ diff[end] ≤ n_entries`
264-
function _sorted_setdiff!(out::Vector{Int}, n_entries::Int, diff::Vector{Int})
265-
n_diff = length(diff)
266-
resize!(out, n_entries - n_diff)
267-
diff_ind = out_ind = 1
268-
for i in 1:n_entries
269-
if diff_ind n_diff && i == diff[diff_ind]
270-
diff_ind += 1
271-
else
272-
out[out_ind] = i
273-
out_ind += 1
274-
end
263+
function _set_freedofs!(free_dofs::Vector{Int}, isconstrained::BitVector, num_dofs::Int, num_prescribed::Int)
264+
resize!(free_dofs, num_dofs - num_prescribed)
265+
j = 1
266+
for i in 1:num_dofs
267+
isconstrained[i] && continue
268+
free_dofs[j] = i
269+
j += 1
275270
end
276-
return out
271+
return free_dofs
277272
end
278273

279274
"""
@@ -291,7 +286,12 @@ function close!(ch::ConstraintHandler)
291286
ch.affine_inhomogeneities .= ch.affine_inhomogeneities[I]
292287
ch.dofcoefficients .= ch.dofcoefficients[I]
293288

294-
_sorted_setdiff!(ch.free_dofs, ndofs(ch.dh), ch.prescribed_dofs)
289+
resize!(ch.isconstrained, ndofs(ch.dh))
290+
fill!(ch.isconstrained, false)
291+
for dof in ch.prescribed_dofs
292+
ch.isconstrained[dof] = true
293+
end
294+
_set_freedofs!(ch.free_dofs, ch.isconstrained, ndofs(ch.dh), length(ch.prescribed_dofs))
295295

296296
for i in 1:length(ch.prescribed_dofs)
297297
ch.dofmapping[ch.prescribed_dofs[i]] = i
@@ -913,11 +913,12 @@ function zero_out_columns!(K::AbstractSparseMatrixCSC, ch::ConstraintHandler) #
913913
end
914914

915915
function zero_out_rows!(K::AbstractSparseMatrixCSC, ch::ConstraintHandler)
916+
@boundscheck checkbounds(ch.isconstrained, axes(K, 1))
916917
rowval = K.rowval
917918
nzval = K.nzval
918-
@inbounds for i in eachindex(rowval, nzval)
919-
if haskey(ch.dofmapping, rowval[i])
920-
nzval[i] = 0
919+
@inbounds for (i, row) in pairs(rowval)
920+
if ch.isconstrained[row]
921+
nzval[i] = zero(eltype(K))
921922
end
922923
end
923924
return
@@ -1765,7 +1766,7 @@ function _apply_local!(
17651766
# 3. Condense any affine constraints
17661767
if has_nontrivial_affine_constraints
17671768
# Condense this constraint locally if possible, and otherwise modifies the global arrays.
1768-
_condense_local!(local_matrix, local_vector, global_matrix, global_vector, global_dofs, ch.dofmapping, ch.dofcoefficients)
1769+
_condense_local!(local_matrix, local_vector, global_matrix, global_vector, global_dofs, ch.dofmapping, ch.dofcoefficients, ch.isconstrained)
17691770
end
17701771
# 4. Zero out columns/rows of local matrix and replace diagonal entries with the mean
17711772
if has_constraints
@@ -1794,15 +1795,17 @@ end
17941795
"""
17951796
_condense_local!(local_matrix::AbstractMatrix, local_vector::AbstractVector,
17961797
global_matrix#=::SparseMatrixCSC=#, global_vector#=::Vector=#,
1797-
global_dofs::AbstractVector, dofmapping::Dict, dofcoefficients::Vector)
1798+
global_dofs::AbstractVector, dofmapping::Dict, dofcoefficients::Vector,
1799+
isconstrained::BitVector)
17981800
17991801
Condensation of affine constraints on element level. If possible this function only
18001802
modifies the local arrays.
18011803
"""
18021804
function _condense_local!(
18031805
local_matrix::AbstractMatrix, local_vector::AbstractVector,
18041806
global_matrix #=::SparseMatrixCSC=#, global_vector #=::Vector=#,
1805-
global_dofs::AbstractVector, dofmapping::Dict, dofcoefficients::Vector
1807+
global_dofs::AbstractVector, dofmapping::Dict, dofcoefficients::Vector,
1808+
isconstrained::BitVector,
18061809
)
18071810
@assert axes(local_matrix, 1) == axes(local_matrix, 2) ==
18081811
axes(local_vector, 1) == axes(global_dofs, 1)
@@ -1821,7 +1824,7 @@ function _condense_local!(
18211824
if local_mrow === nothing
18221825
# Only modify the global array if this isn't prescribed since we
18231826
# can't zero it out later like with the local matrix.
1824-
if !haskey(dofmapping, global_col) && !haskey(dofmapping, global_mrow)
1827+
if !isconstrained[global_col] && !isconstrained[global_mrow]
18251828
has_global_arrays || missing_global()
18261829
addindex!(global_matrix, mw, global_mrow, global_col)
18271830
end

0 commit comments

Comments
 (0)