Skip to content

Commit c614def

Browse files
committed
Use manual construction of sparse matrix
1 parent 85b6037 commit c614def

File tree

4 files changed

+59
-35
lines changed

4 files changed

+59
-35
lines changed

Project.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ DocStringExtensions = "ffbed154-4ef7-542d-bbb7-c09d3a79fcae"
1313
ExtendableFEMBase = "12fb9182-3d4c-4424-8fd1-727a0899810c"
1414
ExtendableGrids = "cfc395e8-590f-11e8-1f13-43a2532b2fa8"
1515
ExtendableSparse = "95c220a8-a1cf-11e9-0c77-dbfce5f500b3"
16+
FillArrays = "1a297f60-69ca-5386-bcde-b61e274b549b"
1617
ForwardDiff = "f6369f11-7733-5829-9624-2563aa707210"
1718
GridVisualize = "5eed8a63-0fb0-45eb-886d-8d5a387d12b8"
1819
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
@@ -38,6 +39,7 @@ ExplicitImports = "1"
3839
ExtendableFEMBase = "1.3.0"
3940
ExtendableGrids = "1.10.3"
4041
ExtendableSparse = "1.5.3"
42+
FillArrays = "1.13.0"
4143
ForwardDiff = "0.10.35,1"
4244
GridVisualize = "1.8.1"
4345
IncompleteLU = "0.2.1"

src/ExtendableFEM.jl

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

8-
using BlockArrays: BlockMatrix, BlockVector, Block
98
using ChunkSplitters: chunks
9+
using BlockArrays: BlockMatrix, BlockVector, Block, blocks, axes
1010
using CommonSolve: CommonSolve
1111
using DiffResults: DiffResults
1212
using DocStringExtensions: DocStringExtensions, TYPEDEF, TYPEDSIGNATURES
@@ -61,6 +61,7 @@ using ExtendableGrids: ExtendableGrids, AT_NODES, AbstractElementGeometry,
6161
using ExtendableSparse: ExtendableSparse, ExtendableSparseMatrix, flush!,
6262
MTExtendableSparseMatrixCSC, findindex,
6363
rawupdateindex!
64+
using FillArrays: Zeros
6465
using ForwardDiff: ForwardDiff
6566
using GridVisualize: GridVisualize, GridVisualizer, gridplot!, reveal, save,
6667
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)