Browse Source

Add solve(!) methods for PartitionedArrays input.

This patch adds the following methods:

    solve( ::HYPRESolver,            ::PSparseMatrix, ::PVector)
    solve!(::HYPRESolver, ::PVector, ::PSparseMatrix, ::PVector)

which automatically converts to/from HYPRE(Matrix|Vector).
fe/wip
Fredrik Ekre 3 years ago
parent
commit
63bac29c7a
  1. 20
      src/solvers.jl
  2. 50
      test/runtests.jl

20
src/solvers.jl

@ -31,6 +31,26 @@ See also [`solve`](@ref).
solve!(pcg::HYPRESolver, x::HYPREVector, A::HYPREMatrix, ::HYPREVector) solve!(pcg::HYPRESolver, x::HYPREVector, A::HYPREMatrix, ::HYPREVector)
######################################
# PartitionedArrays solver interface #
######################################
# TODO: Would it be useful with a method that copied the solution to b instead?
function solve(solver::HYPRESolver, A::PSparseMatrix, b::PVector)
hypre_x = solve(solver, HYPREMatrix(A), HYPREVector(b))
# TODO: This could be a HYPREVector -> PVector conversion
x = copy!(copy(b), hypre_x)
return x
end
function solve!(solver::HYPRESolver, x::PVector, A::PSparseMatrix, b::PVector)
hypre_x = HYPREVector(x)
solve!(solver, hypre_x, HYPREMatrix(A), HYPREVector(b))
copy!(x, hypre_x)
return x
end
############# #############
# BoomerAMG # # BoomerAMG #
############# #############

50
test/runtests.jl

@ -65,7 +65,7 @@ end
end end
function tomain(x) function tomain(x)
g = gather(x) g = gather(copy(x))
be = get_backend(g.values) be = get_backend(g.values)
if be isa SequentialBackend if be isa SequentialBackend
return g.values.parts[1] return g.values.parts[1]
@ -107,7 +107,7 @@ end
CSC = PSparseMatrix(diag_data(backend, parts)...; ids=:global) CSC = PSparseMatrix(diag_data(backend, parts)...; ids=:global)
CSR = PSparseMatrix(sparsecsr, diag_data(backend, parts)...; ids=:global) CSR = PSparseMatrix(sparsecsr, diag_data(backend, parts)...; ids=:global)
@test tomain(copy(CSC)) == tomain(copy(CSR)) == @test tomain(CSC) == tomain(CSR) ==
Diagonal([1, 2, 3, 8, 10, 12, 7, 8, 9, 10]) Diagonal([1, 2, 3, 8, 10, 12, 7, 8, 9, 10])
map_parts(CSC.values, CSC.rows.partition, CSC.cols.partition, map_parts(CSC.values, CSC.rows.partition, CSC.cols.partition,
@ -141,7 +141,7 @@ end
CSC = PSparseMatrix(diag_data(backend, parts)...; ids=:global) CSC = PSparseMatrix(diag_data(backend, parts)...; ids=:global)
CSR = PSparseMatrix(sparsecsr, diag_data(backend, parts)...; ids=:global) CSR = PSparseMatrix(sparsecsr, diag_data(backend, parts)...; ids=:global)
@test tomain(copy(CSC)) == tomain(copy(CSR)) == @test tomain(CSC) == tomain(CSR) ==
Diagonal([1, 2, 3, 8, 10, 12, 7, 8, 9, 10]) Diagonal([1, 2, 3, 8, 10, 12, 7, 8, 9, 10])
map_parts(CSC.values, CSC.rows.partition, CSC.cols.partition, map_parts(CSC.values, CSC.rows.partition, CSC.cols.partition,
@ -223,13 +223,13 @@ end
add_gids!(rows, I) add_gids!(rows, I)
pb = PVector(I, V, rows; ids=:global) pb = PVector(I, V, rows; ids=:global)
assemble!(pb) assemble!(pb)
@test tomain(copy(pb)) == [i in 4:6 ? 2x : x for (i, x) in zip(eachindex(b), b)] @test tomain(pb) == [i in 4:6 ? 2x : x for (i, x) in zip(eachindex(b), b)]
H = HYPREVector(pb) H = HYPREVector(pb)
@test H.IJVector != HYPRE_IJVector(C_NULL) @test H.IJVector != HYPRE_IJVector(C_NULL)
@test H.ParVector != HYPRE_ParVector(C_NULL) @test H.ParVector != HYPRE_ParVector(C_NULL)
pbc = fill!(copy(pb), 0) pbc = fill!(copy(pb), 0)
copy!(pbc, H) copy!(pbc, H)
@test tomain(copy(pbc)) == tomain(copy(pb)) @test tomain(pbc) == tomain(pb)
# MPI backend # MPI backend
backend = MPIBackend() backend = MPIBackend()
parts = get_part_ids(backend, 1) parts = get_part_ids(backend, 1)
@ -240,13 +240,13 @@ end
add_gids!(rows, I) add_gids!(rows, I)
pb = PVector(I, V, rows; ids=:global) pb = PVector(I, V, rows; ids=:global)
assemble!(pb) assemble!(pb)
@test tomain(copy(pb)) == b @test tomain(pb) == b
H = HYPREVector(pb) H = HYPREVector(pb)
@test H.IJVector != HYPRE_IJVector(C_NULL) @test H.IJVector != HYPRE_IJVector(C_NULL)
@test H.ParVector != HYPRE_ParVector(C_NULL) @test H.ParVector != HYPRE_ParVector(C_NULL)
pbc = fill!(copy(pb), 0) pbc = fill!(copy(pb), 0)
copy!(pbc, H) copy!(pbc, H)
@test tomain(copy(pbc)) == tomain(copy(pb)) @test tomain(pbc) == tomain(pb)
end end
@testset "BoomerAMG" begin @testset "BoomerAMG" begin
@ -303,3 +303,39 @@ end
copy!(x, x_h) copy!(x, x_h)
@test x A \ b atol=tol @test x A \ b atol=tol
end end
function topartitioned(x::Vector, A::SparseMatrixCSC, b::Vector)
parts = get_part_ids(SequentialBackend(), 1)
rows = PRange(parts, size(A, 1))
cols = PRange(parts, size(A, 2))
II, JJ, VV, bb, xx = map_parts(parts) do _
return findnz(A)..., b, x
end
add_gids!(rows, II)
assemble!(II, JJ, VV, rows)
add_gids!(cols, JJ)
A_p = PSparseMatrix(II, JJ, VV, rows, cols; ids = :global)
b_p = PVector(bb, rows)
x_p = PVector(xx, cols)
return x_p, A_p, b_p
end
@testset "solve with PartitionedArrays" begin
# Setup
A = sprand(100, 100, 0.05); A = A'A + 5I
b = rand(100)
x = zeros(100)
x_p, A_p, b_p = topartitioned(x, A, b)
@test A == tomain(A_p)
@test b == tomain(b_p)
@test x == tomain(x_p)
# Solve
tol = 1e-9
pcg = HYPRE.PCG(; Tol = tol)
## solve!
HYPRE.solve!(pcg, x_p, A_p, b_p)
@test tomain(x_p) A \ b atol=tol
## solve
x_p = HYPRE.solve(pcg, A_p, b_p)
@test tomain(x_p) A \ b atol=tol
end

Loading…
Cancel
Save