@@ -250,51 +250,72 @@ function solve_linear_system!(A, b, sol, soltemp, residual, linsolve, unknowns,
250
250
b_unrestricted = residual. entries
251
251
end
252
252
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
264
257
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 ]
265
263
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 ]. .. ]
269
273
270
- total_size = sum (block_sizes)
271
- Tv = eltype (A_unrestricted)
274
+ total_size = sum (block_sizes)
275
+ Tv = eltype (A_unrestricted)
272
276
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
276
280
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
279
283
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
283
287
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]
288
292
293
+ end
289
294
end
290
- end
291
295
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
293
307
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))
297
309
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
298
319
end
299
320
end
300
321
0 commit comments