@@ -250,51 +250,72 @@ function solve_linear_system!(A, b, sol, soltemp, residual, linsolve, unknowns,
250250 b_unrestricted = residual. entries
251251 end
252252
253- @timeit timer " LM restrictions" begin
254- # # add possible Lagrange restrictions
255- @timeit timer " prepare" begin
256- restriction_matrices = [length (freedofs) > 0 ? re. parameters[:matrix ][freedofs, :] : re. parameters[:matrix ] for re in PD. restrictions ]
257- restriction_rhs = [length (freedofs) > 0 ? re. parameters[:rhs ][freedofs] : re. parameters[:rhs ] for re in PD. restrictions ]
258-
259- # # we need to add the (initial) solution to the rhs, since we work with the residual equation
260- for (B, rhs) in zip (restriction_matrices, restriction_rhs)
261- rhs .+ = B' sol. entries
262- end
263- end
253+ if length (PD. restrictions) == 0
254+ linsolve. A = A_unrestricted
255+ linsolve. b = b_unrestricted
256+ else
264257
258+ @timeit timer " LM restrictions" begin
259+ # # add possible Lagrange restrictions
260+ @timeit timer " prepare" begin
261+ restriction_matrices = [length (freedofs) > 0 ? re. parameters[:matrix ][freedofs, :] : re. parameters[:matrix ] for re in PD. restrictions ]
262+ restriction_rhs = [length (freedofs) > 0 ? re. parameters[:rhs ][freedofs] : re. parameters[:rhs ] for re in PD. restrictions ]
265263
266- @timeit timer " compute blocks" begin
267- # block sizes for the block matrix
268- block_sizes = [size (A_unrestricted, 2 ), [ size (B, 2 ) for B in restriction_matrices ]. .. ]
264+ # # we need to add the (initial) solution to the rhs, since we work with the residual equation
265+ for (B, rhs) in zip (restriction_matrices, restriction_rhs)
266+ rhs .+ = B' sol. entries
267+ end
268+ end
269+
270+ @timeit timer " set blocks" begin
271+ # block sizes for the block matrix
272+ block_sizes = [size (A_unrestricted, 2 ), [ size (B, 2 ) for B in restriction_matrices ]. .. ]
269273
270- total_size = sum (block_sizes)
271- Tv = eltype (A_unrestricted)
274+ total_size = sum (block_sizes)
275+ Tv = eltype (A_unrestricted)
272276
273- # # create block matrix
274- A_block = BlockMatrix (spzeros (Tv, total_size, total_size), block_sizes, block_sizes)
275- A_block[Block (1 , 1 )] = A_unrestricted
277+ # # create block matrix
278+ A_block = BlockMatrix (spzeros (Tv, total_size, total_size), block_sizes, block_sizes)
279+ A_block[Block (1 , 1 )] = A_unrestricted
276280
277- b_block = BlockVector (zeros (Tv, total_size), block_sizes)
278- b_block[Block (1 )] = b_unrestricted
281+ b_block = BlockVector (zeros (Tv, total_size), block_sizes)
282+ b_block[Block (1 )] = b_unrestricted
279283
280- u_unrestricted = linsolve. u
281- u_block = BlockVector (zeros (Tv, total_size), block_sizes)
282- u_block[Block (1 )] = u_unrestricted
284+ u_unrestricted = linsolve. u
285+ u_block = BlockVector (zeros (Tv, total_size), block_sizes)
286+ u_block[Block (1 )] = u_unrestricted
283287
284- for i in eachindex (PD. restrictions)
285- A_block[Block (1 , i + 1 )] = restriction_matrices[i]
286- A_block[Block (i + 1 , 1 )] = transpose (restriction_matrices[i])
287- b_block[Block (i + 1 )] = restriction_rhs[i]
288+ for i in eachindex (PD. restrictions)
289+ A_block[Block (1 , i + 1 )] = restriction_matrices[i]
290+ A_block[Block (i + 1 , 1 )] = transpose (restriction_matrices[i])
291+ b_block[Block (i + 1 )] = restriction_rhs[i]
288292
293+ end
289294 end
290- end
291295
292- @timeit timer " convert" begin
296+ @timeit timer " convert" begin
297+
298+ linsolve. b = Vector (b_block) # convert to dense vector
299+ linsolve. u = Vector (u_block) # convert to dense vector
300+
301+ # linsolve.A = sparse(A_block) # convert to CSC Matrix is very slow https://github.com/JuliaArrays/BlockArrays.jl/issues/78
302+ # do it manually:
303+ A_flat = spzeros (size (A_block))
304+
305+ lasts_i = [0 , axes (A_block)[1 ]. lasts... ] # add zero
306+ lasts_j = [0 , axes (A_block)[2 ]. lasts... ] # add zero
293307
294- linsolve. A = sparse (A_block) # convert to CSC Matrix
295- linsolve. b = Vector (b_block) # convert to dense vector
296- linsolve. u = Vector (u_block) # convert to dense vector
308+ (ni, nj) = size (blocks (A_block))
297309
310+ for i in 1 : ni, j in 1 : nj
311+ range_i = (lasts_i[i] + 1 ): lasts_i[i + 1 ]
312+ range_j = (lasts_j[j] + 1 ): lasts_j[j + 1 ]
313+
314+ # write each block directly in the resulting matrix
315+ A_flat[range_i, range_j] = A_block[Block (i, j)]
316+ end
317+ linsolve. A = A_flat
318+ end
298319 end
299320 end
300321
0 commit comments