mirror of https://github.com/fredrikekre/HYPRE.jl
Browse Source
This patch adds an assembler interface such that it is possible to
directly assemble HYPRE(Vector|Matrix) without going through a sparse
matrix datastructure in Julia. This is done as follows:
1. Create a new (empty) matrix/vector using the constructor.
2. Create an assembler and initialize the assembly using
HYPRE.start_assemble!.
3. Assemble all contributions using HYPRE.assemble!.
4. Finalize the assembly using HYPRE.finish_assemble!.
HYPRE.start_assemble!
The assembler caches some buffers that are (re)used by every call to
HYPRE.assemble! so this should be efficient. All MPI communication
should happen in the finalization step.
pull/6/head
6 changed files with 433 additions and 13 deletions
@ -0,0 +1,115 @@ |
|||||||
|
# SPDX-License-Identifier: MIT |
||||||
|
|
||||||
|
using HYPRE |
||||||
|
using MPI |
||||||
|
using Test |
||||||
|
|
||||||
|
MPI.Init() |
||||||
|
HYPRE.Init() |
||||||
|
|
||||||
|
include("test_utils.jl") |
||||||
|
|
||||||
|
comm = MPI.COMM_WORLD |
||||||
|
comm_rank = MPI.Comm_rank(comm) |
||||||
|
comm_size = MPI.Comm_size(comm) |
||||||
|
|
||||||
|
if comm_size != 2 |
||||||
|
error("Must run with 2 ranks.") |
||||||
|
end |
||||||
|
|
||||||
|
if comm_rank == 0 |
||||||
|
ilower = 1 |
||||||
|
iupper = 10 |
||||||
|
N = 2:10 |
||||||
|
else |
||||||
|
ilower = 11 |
||||||
|
iupper = 20 |
||||||
|
N = 11:19 |
||||||
|
end |
||||||
|
|
||||||
|
function values_and_indices(n) |
||||||
|
idx = [n - 1, n, n + 1] |
||||||
|
a = Float64[ |
||||||
|
n -2n -n |
||||||
|
-2n n -2n |
||||||
|
-n -2n n |
||||||
|
] |
||||||
|
b = Float64[n, n/2, n/3] |
||||||
|
return idx, a, b |
||||||
|
end |
||||||
|
|
||||||
|
########################## |
||||||
|
## HYPREMatrixAssembler ## |
||||||
|
########################## |
||||||
|
|
||||||
|
# Dense local matrix |
||||||
|
|
||||||
|
A = HYPREMatrix(comm, ilower, iupper) |
||||||
|
AM = zeros(20, 20) |
||||||
|
for i in 1:2 |
||||||
|
assembler = HYPRE.start_assemble!(A) |
||||||
|
fill!(AM, 0) |
||||||
|
for n in N |
||||||
|
idx, a, _ = values_and_indices(n) |
||||||
|
HYPRE.assemble!(assembler, idx, a) |
||||||
|
AM[idx, idx] += a |
||||||
|
end |
||||||
|
f = HYPRE.finish_assemble!(assembler) |
||||||
|
@test f === A |
||||||
|
MPI.Allreduce!(AM, +, comm) |
||||||
|
@test getindex_debug(A, ilower:iupper, 1:20) == AM[ilower:iupper, 1:20] |
||||||
|
MPI.Barrier(comm) |
||||||
|
end |
||||||
|
|
||||||
|
########################## |
||||||
|
## HYPREVectorAssembler ## |
||||||
|
########################## |
||||||
|
|
||||||
|
# Dense local vector |
||||||
|
|
||||||
|
b = HYPREVector(comm, ilower, iupper) |
||||||
|
bv = zeros(20) |
||||||
|
for i in 1:2 |
||||||
|
assembler = HYPRE.start_assemble!(b) |
||||||
|
fill!(bv, 0) |
||||||
|
for n in N |
||||||
|
idx, _, a = values_and_indices(n) |
||||||
|
HYPRE.assemble!(assembler, idx, a) |
||||||
|
bv[idx] += a |
||||||
|
end |
||||||
|
f = HYPRE.finish_assemble!(assembler) |
||||||
|
@test f === b |
||||||
|
MPI.Allreduce!(bv, +, comm) |
||||||
|
@test getindex_debug(b, ilower:iupper) == bv[ilower:iupper] |
||||||
|
MPI.Barrier(comm) |
||||||
|
end |
||||||
|
|
||||||
|
#################### |
||||||
|
## HYPREAssembler ## |
||||||
|
#################### |
||||||
|
|
||||||
|
# Dense local arrays |
||||||
|
|
||||||
|
A = HYPREMatrix(comm, ilower, iupper) |
||||||
|
AM = zeros(20, 20) |
||||||
|
b = HYPREVector(comm, ilower, iupper) |
||||||
|
bv = zeros(20) |
||||||
|
for i in 1:2 |
||||||
|
assembler = HYPRE.start_assemble!(A, b) |
||||||
|
fill!(AM, 0) |
||||||
|
fill!(bv, 0) |
||||||
|
for n in N |
||||||
|
idx, a, c = values_and_indices(n) |
||||||
|
HYPRE.assemble!(assembler, idx, a, c) |
||||||
|
AM[idx, idx] += a |
||||||
|
bv[idx] += c |
||||||
|
end |
||||||
|
F, f = HYPRE.finish_assemble!(assembler) |
||||||
|
@test F === A |
||||||
|
@test f === b |
||||||
|
MPI.Allreduce!(AM, +, comm) |
||||||
|
MPI.Allreduce!(bv, +, comm) |
||||||
|
@test getindex_debug(A, ilower:iupper, 1:20) == AM[ilower:iupper, 1:20] |
||||||
|
@test getindex_debug(b, ilower:iupper) == bv[ilower:iupper] |
||||||
|
MPI.Barrier(comm) |
||||||
|
end |
||||||
@ -0,0 +1,23 @@ |
|||||||
|
# SPDX-License-Identifier: MIT |
||||||
|
|
||||||
|
using HYPRE |
||||||
|
using HYPRE.LibHYPRE |
||||||
|
using HYPRE.LibHYPRE: @check |
||||||
|
|
||||||
|
function getindex_debug(A::HYPREMatrix, i::AbstractVector, j::AbstractVector) |
||||||
|
nrows = HYPRE_Int(length(i)) |
||||||
|
ncols = fill(HYPRE_Int(length(j)), length(i)) |
||||||
|
rows = convert(Vector{HYPRE_BigInt}, i) |
||||||
|
cols = convert(Vector{HYPRE_BigInt}, repeat(j, length(i))) |
||||||
|
values = Vector{HYPRE_Complex}(undef, length(i) * length(j)) |
||||||
|
@check HYPRE_IJMatrixGetValues(A.ijmatrix, nrows, ncols, rows, cols, values) |
||||||
|
return permutedims(reshape(values, (length(j), length(i)))) |
||||||
|
end |
||||||
|
|
||||||
|
function getindex_debug(b::HYPREVector, i::AbstractVector) |
||||||
|
nvalues = HYPRE_Int(length(i)) |
||||||
|
indices = convert(Vector{HYPRE_BigInt}, i) |
||||||
|
values = Vector{HYPRE_Complex}(undef, length(i)) |
||||||
|
@check HYPRE_IJVectorGetValues(b.ijvector, nvalues, indices, values) |
||||||
|
return values |
||||||
|
end |
||||||
Loading…
Reference in new issue