Browse Source

Rework `HYPRE(Matrix|Vector)` structs and constructors

This patch adds the communicator and the owned rows to the
`HYPRE(Matrix|Vector)` structs. The `Internals.init_(matrix|vector)`
functions have been removed in favor of:

    HYPREMatrix(::MPI.Comm, ::Integer, ::Integer, ::Integer, ::Integer)
    HYPREVector(::MPI.Comm, ::Integer, ::Integer)

which more or less mirrors the `IJ(Matrix|Vector)Create` functions.
fe/copyto
Fredrik Ekre 3 years ago
parent
commit
e179325ba4
  1. 86
      src/HYPRE.jl
  2. 2
      src/Internals.jl
  3. 12
      test/runtests.jl

86
src/HYPRE.jl

@ -24,21 +24,19 @@ include("Internals.jl")
############################### ###############################
mutable struct HYPREMatrix # <: AbstractMatrix{HYPRE_Complex} mutable struct HYPREMatrix # <: AbstractMatrix{HYPRE_Complex}
#= const =# comm::MPI.Comm
#= const =# ilower::HYPRE_BigInt
#= const =# iupper::HYPRE_BigInt
#= const =# jlower::HYPRE_BigInt
#= const =# jupper::HYPRE_BigInt
IJMatrix::HYPRE_IJMatrix IJMatrix::HYPRE_IJMatrix
ParCSRMatrix::HYPRE_ParCSRMatrix ParCSRMatrix::HYPRE_ParCSRMatrix
HYPREMatrix() = new(C_NULL, C_NULL)
end end
mutable struct HYPREVector # <: AbstractVector{HYPRE_Complex} function HYPREMatrix(comm::MPI.Comm, ilower::Integer, iupper::Integer,
IJVector::HYPRE_IJVector jlower::Integer=ilower, jupper::Integer=iupper)
ParVector::HYPRE_ParVector
HYPREVector() = new(C_NULL, C_NULL)
end
# Create a new IJMatrix, set the object type, prepare for setting values
function Internals.init_matrix(comm::MPI.Comm, ilower, iupper)
# Create the IJ matrix # Create the IJ matrix
A = HYPREMatrix() A = HYPREMatrix(comm, ilower, iupper, jlower, jupper, C_NULL, C_NULL)
IJMatrixRef = Ref{HYPRE_IJMatrix}(C_NULL) IJMatrixRef = Ref{HYPRE_IJMatrix}(C_NULL)
@check HYPRE_IJMatrixCreate(comm, ilower, iupper, ilower, iupper, IJMatrixRef) @check HYPRE_IJMatrixCreate(comm, ilower, iupper, ilower, iupper, IJMatrixRef)
A.IJMatrix = IJMatrixRef[] A.IJMatrix = IJMatrixRef[]
@ -51,21 +49,17 @@ function Internals.init_matrix(comm::MPI.Comm, ilower, iupper)
return A return A
end end
# Finalize the matrix and fetch the assembled matrix mutable struct HYPREVector # <: AbstractVector{HYPRE_Complex}
# This should be called after setting all the values #= const =# comm::MPI.Comm
function Internals.assemble_matrix(A::HYPREMatrix) #= const =# ilower::HYPRE_BigInt
# Finalize after setting all values #= const =# iupper::HYPRE_BigInt
@check HYPRE_IJMatrixAssemble(A.IJMatrix) IJVector::HYPRE_IJVector
# Fetch the assembled CSR matrix ParVector::HYPRE_ParVector
ParCSRMatrixRef = Ref{Ptr{Cvoid}}(C_NULL)
@check HYPRE_IJMatrixGetObject(A.IJMatrix, ParCSRMatrixRef)
A.ParCSRMatrix = convert(Ptr{HYPRE_ParCSRMatrix}, ParCSRMatrixRef[])
return A
end end
function Internals.init_vector(comm::MPI.Comm, ilower, iupper) function HYPREVector(comm::MPI.Comm, ilower::Integer, iupper::Integer)
# Create the IJ vector # Create the IJ vector
b = HYPREVector() b = HYPREVector(comm, ilower, iupper, C_NULL, C_NULL)
b_ref = Ref{HYPRE_IJVector}(C_NULL) b_ref = Ref{HYPRE_IJVector}(C_NULL)
@check HYPRE_IJVectorCreate(comm, ilower, iupper, b_ref) @check HYPRE_IJVectorCreate(comm, ilower, iupper, b_ref)
b.IJVector = b_ref[] b.IJVector = b_ref[]
@ -78,6 +72,18 @@ function Internals.init_vector(comm::MPI.Comm, ilower, iupper)
return b return b
end end
# Finalize the matrix and fetch the assembled matrix
# This should be called after setting all the values
function Internals.assemble_matrix(A::HYPREMatrix)
# Finalize after setting all values
@check HYPRE_IJMatrixAssemble(A.IJMatrix)
# Fetch the assembled CSR matrix
ParCSRMatrixRef = Ref{Ptr{Cvoid}}(C_NULL)
@check HYPRE_IJMatrixGetObject(A.IJMatrix, ParCSRMatrixRef)
A.ParCSRMatrix = convert(Ptr{HYPRE_ParCSRMatrix}, ParCSRMatrixRef[])
return A
end
function Internals.assemble_vector(b::HYPREVector) function Internals.assemble_vector(b::HYPREVector)
# Finalize after setting all values # Finalize after setting all values
@check HYPRE_IJVectorAssemble(b.IJVector) @check HYPRE_IJVectorAssemble(b.IJVector)
@ -89,27 +95,29 @@ function Internals.assemble_vector(b::HYPREVector)
end end
function Internals.get_proc_rows(b::HYPREVector) function Internals.get_proc_rows(b::HYPREVector)
jlower_ref = Ref{HYPRE_BigInt}() # ilower_ref = Ref{HYPRE_BigInt}()
jupper_ref = Ref{HYPRE_BigInt}() # iupper_ref = Ref{HYPRE_BigInt}()
@check HYPRE_IJVectorGetLocalRange(b.IJVector, jlower_ref, jupper_ref) # @check HYPRE_IJVectorGetLocalRange(b.IJVector, ilower_ref, iupper_ref)
jlower = jlower_ref[] # ilower = ilower_ref[]
jupper = jupper_ref[] # iupper = iupper_ref[]
return jlower, jupper # return ilower, iupper
return b.ilower, b.iupper
end end
function Internals.get_comm(b::HYPREVector) function Internals.get_comm(b::HYPREVector)
# The MPI communicator is (currently) the first field of the struct: # # The MPI communicator is (currently) the first field of the struct:
# https://github.com/hypre-space/hypre/blob/48de53e675af0e23baf61caa73d89fd9f478f453/src/IJ_mv/IJ_vector.h#L23 # # https://github.com/hypre-space/hypre/blob/48de53e675af0e23baf61caa73d89fd9f478f453/src/IJ_mv/IJ_vector.h#L23
# Fingers crossed this doesn't change! # # Fingers crossed this doesn't change!
@assert b.IJVector != C_NULL # @assert b.IJVector != C_NULL
comm = unsafe_load(Ptr{MPI.Comm}(b.IJVector)) # comm = unsafe_load(Ptr{MPI.Comm}(b.IJVector))
return comm # return comm
return b.comm
end end
function Base.zero(b::HYPREVector) function Base.zero(b::HYPREVector)
jlower, jupper = Internals.get_proc_rows(b) jlower, jupper = Internals.get_proc_rows(b)
comm = Internals.get_comm(b) comm = Internals.get_comm(b)
x = Internals.init_vector(comm, jlower, jupper) x = HYPREVector(comm, jlower, jupper)
# TODO All values 0 by default? Looks like it... Work in progress patch to hypre to # TODO All values 0 by default? Looks like it... Work in progress patch to hypre to
# support IJVectorSetConstantValues analoguous to IJMatrixSetConstantValues. # support IJVectorSetConstantValues analoguous to IJMatrixSetConstantValues.
nvalues = jupper - jlower + 1 nvalues = jupper - jlower + 1
@ -201,7 +209,7 @@ end
# TODO: Default to ilower = 1, iupper = size(B, 1)? # TODO: Default to ilower = 1, iupper = size(B, 1)?
function HYPREMatrix(B::Union{SparseMatrixCSC,SparseMatrixCSR}, ilower, iupper, comm::MPI.Comm=MPI.COMM_WORLD) function HYPREMatrix(B::Union{SparseMatrixCSC,SparseMatrixCSR}, ilower, iupper, comm::MPI.Comm=MPI.COMM_WORLD)
A = Internals.init_matrix(comm, ilower, iupper) A = HYPREMatrix(comm, ilower, iupper)
nrows, ncols, rows, cols, values = Internals.to_hypre_data(B, ilower, iupper) nrows, ncols, rows, cols, values = Internals.to_hypre_data(B, ilower, iupper)
@check HYPRE_IJMatrixSetValues(A.IJMatrix, nrows, ncols, rows, cols, values) @check HYPRE_IJMatrixSetValues(A.IJMatrix, nrows, ncols, rows, cols, values)
Internals.assemble_matrix(A) Internals.assemble_matrix(A)
@ -222,7 +230,7 @@ end
# TODO: Default to ilower = 1, iupper = length(x)? # TODO: Default to ilower = 1, iupper = length(x)?
function HYPREVector(x::Vector, ilower, iupper, comm=MPI.COMM_WORLD) function HYPREVector(x::Vector, ilower, iupper, comm=MPI.COMM_WORLD)
b = Internals.init_vector(comm, ilower, iupper) b = HYPREVector(comm, ilower, iupper)
nvalues, indices, values = Internals.to_hypre_data(x, ilower, iupper) nvalues, indices, values = Internals.to_hypre_data(x, ilower, iupper)
@check HYPRE_IJVectorSetValues(b.IJVector, nvalues, indices, values) @check HYPRE_IJVectorSetValues(b.IJVector, nvalues, indices, values)
Internals.assemble_vector(b) Internals.assemble_vector(b)
@ -360,7 +368,7 @@ function HYPREMatrix(B::PSparseMatrix)
# Fetch rows owned by this process # Fetch rows owned by this process
ilower, iupper = Internals.get_proc_rows(B) ilower, iupper = Internals.get_proc_rows(B)
# Create the IJ matrix # Create the IJ matrix
A = Internals.init_matrix(comm, ilower, iupper) A = HYPREMatrix(comm, ilower, iupper)
# Set all the values # Set all the values
map_parts(B.values, B.rows.partition, B.cols.partition) do Bv, Br, Bc map_parts(B.values, B.rows.partition, B.cols.partition) do Bv, Br, Bc
nrows, ncols, rows, cols, values = Internals.to_hypre_data(Bv, Br, Bc) nrows, ncols, rows, cols, values = Internals.to_hypre_data(Bv, Br, Bc)
@ -382,7 +390,7 @@ function HYPREVector(v::PVector)
# Fetch rows owned by this process # Fetch rows owned by this process
ilower, iupper = Internals.get_proc_rows(v) ilower, iupper = Internals.get_proc_rows(v)
# Create the IJ vector # Create the IJ vector
b = Internals.init_vector(comm, ilower, iupper) b = HYPREVector(comm, ilower, iupper)
# Set all the values # Set all the values
map_parts(v.values, v.owned_values, v.rows.partition) do _, vo, vr map_parts(v.values, v.owned_values, v.rows.partition) do _, vo, vr
ilower_part = vr.lid_to_gid[vr.oid_to_lid.start] ilower_part = vr.lid_to_gid[vr.oid_to_lid.start]

2
src/Internals.jl

@ -6,8 +6,6 @@ function check_n_rows end
function to_hypre_data end function to_hypre_data end
function get_comm end function get_comm end
function get_proc_rows end function get_proc_rows end
function init_matrix end
function init_vector end
function assemble_matrix end function assemble_matrix end
function assemble_vector end function assemble_vector end
function set_options end function set_options end

12
test/runtests.jl

@ -14,11 +14,7 @@ MPI.Init()
HYPRE_Init() HYPRE_Init()
@testset "HYPREMatrix" begin @testset "HYPREMatrix" begin
H = HYPREMatrix() H = HYPREMatrix(MPI.COMM_WORLD, 1, 5)
@test H.IJMatrix == HYPRE_IJMatrix(C_NULL)
@test H.ParCSRMatrix == HYPRE_ParCSRMatrix(C_NULL)
H = Internals.init_matrix(MPI.COMM_WORLD, 1, 5)
@test H.IJMatrix != HYPRE_IJMatrix(C_NULL) @test H.IJMatrix != HYPRE_IJMatrix(C_NULL)
@test H.ParCSRMatrix == HYPRE_ParCSRMatrix(C_NULL) @test H.ParCSRMatrix == HYPRE_ParCSRMatrix(C_NULL)
Internals.assemble_matrix(H) Internals.assemble_matrix(H)
@ -164,11 +160,7 @@ end
end end
@testset "HYPREVector" begin @testset "HYPREVector" begin
h = HYPREVector() h = HYPREVector(MPI.COMM_WORLD, 1, 5)
@test h.IJVector == HYPRE_IJVector(C_NULL)
@test h.ParVector == HYPRE_ParVector(C_NULL)
h = Internals.init_vector(MPI.COMM_WORLD, 1, 5)
@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)
Internals.assemble_vector(h) Internals.assemble_vector(h)

Loading…
Cancel
Save