@@ -19,7 +19,7 @@ struct SparseMatrixAssembler{
1919 mass_storage:: Storage1
2020 residual_storage:: Storage2
2121 residual_unknowns:: Storage1
22- scalar_quadarature_storage :: Storage3 # useful for energy like calculations
22+ scalar_quadrature_storage :: Storage3 # useful for energy like calculations
2323 stiffness_storage:: Storage1
2424 stiffness_action_storage:: Storage2
2525 stiffness_action_unknowns:: Storage1
@@ -110,48 +110,63 @@ function _assemble_element!(
110110 return nothing
111111end
112112
113- """
114- $(TYPEDSIGNATURES)
115- TODO add symbol to interface
116- """
117- function SparseArrays. sparse! (
118- assembler:: SparseMatrixAssembler , :: Val{:stiffness}
113+ # TODO this only work on CPU right now
114+ function _adjust_matrix_entries_for_condensed! (
115+ A:: SparseMatrixCSC , constraint_storage, :: KA.CPU ;
116+ penalty_scale = 1.e6
119117)
120- pattern = assembler. pattern
121- storage = assembler. stiffness_storage
122- return @views SparseArrays. sparse! (
123- pattern. Is, pattern. Js, storage[assembler. pattern. unknown_dofs],
124- length (pattern. klasttouch), length (pattern. klasttouch), + , pattern. klasttouch,
125- pattern. csrrowptr, pattern. csrcolval, pattern. csrnzval,
126- pattern. csccolptr, pattern. cscrowval, pattern. cscnzval
127- )
128- end
118+ # first ensure things are the right size
119+ @assert size (A, 1 ) == size (A, 2 )
120+ @assert length (constraint_storage) == size (A, 2 )
121+
122+ # hacky for now
123+ # need a penalty otherwise we get into trouble with
124+ # iterative linear solvers even for a simple poisson problem
125+ # TODO perhaps this should be optional somehow
126+ penalty = penalty_scale * tr (A) / size (A, 2 )
127+
128+ # now modify A => (I - G) * A + G
129+ nz = nonzeros (A)
130+ rowval = rowvals (A)
131+ for j in 1 : size (A, 2 )
132+ col_start = A. colptr[j]
133+ col_end = A. colptr[j + 1 ] - 1
134+ for k in col_start: col_end
135+ # for (I - G) * A term
136+ nz[k] = (1. - constraint_storage[j]) * nz[k]
137+
138+ # for + G term
139+ if rowval[k] == j
140+ @inbounds nz[k] = nz[k] + penalty * constraint_storage[j]
141+ end
142+ end
143+ end
129144
130- """
131- $(TYPEDSIGNATURES)
132- TODO add symbol to interface
133- """
134- function SparseArrays. sparse! (assembler:: SparseMatrixAssembler , :: Val{:mass} )
135- pattern = assembler. pattern
136- storage = assembler. mass_storage
137- return @views SparseArrays. sparse! (
138- pattern. Is, pattern. Js, storage[assembler. pattern. unknown_dofs],
139- length (pattern. klasttouch), length (pattern. klasttouch), + , pattern. klasttouch,
140- pattern. csrrowptr, pattern. csrcolval, pattern. csrnzval,
141- pattern. csccolptr, pattern. cscrowval, pattern. cscnzval
142- )
145+ return nothing
143146end
144147
145148function constraint_matrix (assembler:: SparseMatrixAssembler )
146149 return Diagonal (assembler. constraint_storage)
147150end
148151
149152function _mass (assembler:: SparseMatrixAssembler , :: KA.CPU )
150- return SparseArrays. sparse! (assembler, Val {:mass} ())
153+ M = SparseArrays. sparse! (assembler. pattern, assembler. mass_storage)
154+
155+ if _is_condensed (assembler. dof)
156+ _adjust_matrix_entries_for_condensed! (M, assembler. constraint_storage, KA. get_getbackend (assembler))
157+ end
158+
159+ return M
151160end
152161
153162function _stiffness (assembler:: SparseMatrixAssembler , :: KA.CPU )
154- return SparseArrays. sparse! (assembler, Val {:stiffness} ())
163+ K = SparseArrays. sparse! (assembler. pattern, assembler. stiffness_storage)
164+
165+ if _is_condensed (assembler. dof)
166+ _adjust_matrix_entries_for_condensed! (K, assembler. constraint_storage, KA. get_backend (assembler))
167+ end
168+
169+ return K
155170end
156171
157172# TODO probably only works for H1 fields
0 commit comments