Skip to content

Commit 92b3a00

Browse files
committed
Use manual construction of sparse matrix
1 parent 538b4f5 commit 92b3a00

4 files changed

Lines changed: 59 additions & 35 deletions

File tree

Project.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ DocStringExtensions = "ffbed154-4ef7-542d-bbb7-c09d3a79fcae"
1111
ExtendableFEMBase = "12fb9182-3d4c-4424-8fd1-727a0899810c"
1212
ExtendableGrids = "cfc395e8-590f-11e8-1f13-43a2532b2fa8"
1313
ExtendableSparse = "95c220a8-a1cf-11e9-0c77-dbfce5f500b3"
14+
FillArrays = "1a297f60-69ca-5386-bcde-b61e274b549b"
1415
ForwardDiff = "f6369f11-7733-5829-9624-2563aa707210"
1516
GridVisualize = "5eed8a63-0fb0-45eb-886d-8d5a387d12b8"
1617
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
@@ -34,6 +35,7 @@ ExplicitImports = "1"
3435
ExtendableFEMBase = "1.3.0"
3536
ExtendableGrids = "1.10.3"
3637
ExtendableSparse = "1.5.3"
38+
FillArrays = "1.13.0"
3739
ForwardDiff = "0.10.35,1"
3840
GridVisualize = "1.8.1"
3941
IncompleteLU = "0.2.1"

src/ExtendableFEM.jl

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ $(read(joinpath(@__DIR__, "..", "README.md"), String))
55
"""
66
module ExtendableFEM
77

8-
using BlockArrays: BlockMatrix, BlockVector, Block
8+
using BlockArrays: BlockMatrix, BlockVector, Block, BlockedMatrix, blocks, axes
99
using CommonSolve: CommonSolve
1010
using DiffResults: DiffResults
1111
using DocStringExtensions: DocStringExtensions, TYPEDEF, TYPEDSIGNATURES
@@ -60,6 +60,7 @@ using ExtendableGrids: ExtendableGrids, AT_NODES, AbstractElementGeometry,
6060
using ExtendableSparse: ExtendableSparse, ExtendableSparseMatrix, flush!,
6161
MTExtendableSparseMatrixCSC, findindex,
6262
rawupdateindex!
63+
using FillArrays: Zeros
6364
using ForwardDiff: ForwardDiff
6465
using GridVisualize: GridVisualize, GridVisualizer, gridplot!, reveal, save,
6566
scalarplot!, vectorplot!

src/common_restrictions/coupled_dofs_restriction.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ function assemble!(R::CoupledDofsRestriction, SC; kwargs...)
3232
B = (R.coupling_matrix - LinearAlgebra.I)[:, unique_cols]
3333

3434
R.parameters[:matrix] = B
35-
return R.parameters[:rhs] = Zeros(length(unique_cols))
35+
R.parameters[:rhs] = Zeros(length(unique_cols))
3636

3737
return nothing
3838
end

src/solvers.jl

Lines changed: 54 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)