@@ -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 )
182183end
183184
@@ -259,21 +260,15 @@ isclosed(ch::ConstraintHandler) = ch.closed
259260free_dofs (ch:: ConstraintHandler ) = ch. free_dofs
260261prescribed_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
277272end
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) #
913913end
914914
915915function 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
17991801Condensation of affine constraints on element level. If possible this function only
18001802modifies the local arrays.
18011803"""
18021804function _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