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 @@
@@ -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 @@
@@ -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