Skip to content

Commit 1bd216c

Browse files
author
Jeremy E Kozdon
committed
WIP: Working on KSP
1 parent 969b287 commit 1bd216c

6 files changed

Lines changed: 155 additions & 75 deletions

File tree

src/ksp.jl

Lines changed: 62 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -2,37 +2,88 @@ const CKSP = Ptr{Cvoid}
22
const CKSPType = Cstring
33

44
abstract type AbstractKSP{PetscLib, PetscScalar} <: Factorization{PetscScalar} end
5-
6-
Base.@kwdef mutable struct KSP{PetscLib, PetscScalar} <: AbstractKSP{PetscLib, PetscScalar}
5+
6+
Base.@kwdef mutable struct KSP{PetscLib, PetscScalar} <:
7+
AbstractKSP{PetscLib, PetscScalar}
78
ptr::CKSP = C_NULL
89
opts::Options{PetscLib} = Options(PetscLib)
910
A::Union{AbstractMat, Nothing} = nothing
11+
P::Union{AbstractMat, Nothing} = nothing
1012
end
1113

12-
function KSP(A::AbstractMat{PetscLib}; kwargs...) where PetscLib
14+
function KSP(
15+
A::AbstractMat{PetscLib},
16+
P::AbstractMat{PetscLib} = A;
17+
kwargs...,
18+
) where {PetscLib}
1319
@assert initialized(PetscLib)
1420
opts = Options(PetscLib; kwargs...)
1521
PetscScalar = PetscLib.PetscScalar
16-
ksp = KSP{PetscLib, PetscScalar}(opts=opts, A = A)
17-
#=
22+
ksp = KSP{PetscLib, PetscScalar}(opts = opts)
23+
comm = getcomm(A)
24+
1825
with(ksp.opts) do
19-
@chk ccall((:KSPCreate, $libpetsc), PetscErrorCode, (MPI.MPI_Comm, Ptr{CKSP}), comm, ksp)
26+
LibPETSc.KSPCreate(PetscLib, comm, ksp)
2027
end
21-
if comm == MPI.COMM_SELF
28+
29+
setoperators!(ksp, A, P)
30+
setfromoptions!(ksp)
31+
32+
# If there is only one rank we can finalize the KSP with GC
33+
if MPI.Comm_size(comm) == 1
2234
finalizer(destroy, ksp)
2335
end
24-
=#
36+
37+
return ksp
38+
end
39+
40+
function setoperators!(
41+
ksp::AbstractKSP{PetscLib},
42+
A::AbstractMat{PetscLib},
43+
P::AbstractMat{PetscLib} = A,
44+
) where {PetscLib}
45+
LibPETSc.KSPSetOperators(PetscLib, ksp, A, P)
46+
ksp.A = A
47+
ksp.P = P
2548
return ksp
2649
end
2750

51+
function setfromoptions!(ksp::AbstractKSP{PetscLib}) where {PetscLib}
52+
with(ksp.opts) do
53+
LibPETSc.KSPSetFromOptions(PetscLib, ksp)
54+
end
55+
end
56+
57+
function destroy(ksp::AbstractKSP{PetscLib}) where {PetscLib}
58+
finalized(PetscLib) || LibPETSc.MatDestroy(PetscLib, ksp)
59+
return nothing
60+
end
61+
62+
function solve!(
63+
x::AbstractVec{PetscLib},
64+
ksp::AbstractKSP{PetscLib},
65+
b::AbstractVec{PetscLib},
66+
) where {PetscLib}
67+
with(ksp.opts) do
68+
LibPETSc.KSPSolve(PetscLib, ksp, b, x)
69+
end
70+
return x
71+
end
72+
73+
function LinearAlgebra.ldiv!(x::AbstractVec, ksp::AbstractKSP, b::AbstractVec)
74+
solve!(x, ksp, b)
75+
end
76+
#=
77+
function Base.:\(ksp::AbstractKSP, b::AbstractVec)
78+
ldiv!(similar(b), ksp, b)
79+
end
80+
=#
81+
2882
#=
2983
struct WrappedKSP{T, PetscLib} <: AbstractKSP{T, PetscLib}
3084
ptr::CKSP
3185
end
3286
33-
scalartype(::KSP{T}) where {T} = T
34-
Base.eltype(::KSP{T}) where {T} = T
35-
3687
LinearAlgebra.transpose(ksp) = LinearAlgebra.Transpose(ksp)
3788
LinearAlgebra.adjoint(ksp) = LinearAlgebra.Adjoint(ksp)
3889
@@ -80,32 +131,6 @@ struct Fn_KSPComputeOperators{T} end
80131
81132
@for_libpetsc begin
82133
83-
function KSP{$PetscScalar}(comm::MPI.Comm; kwargs...)
84-
@assert initialized($petsclib)
85-
opts = Options($petsclib, kwargs...)
86-
ksp = KSP{$PetscScalar, $PetscLib}(opts=opts)
87-
with(ksp.opts) do
88-
@chk ccall((:KSPCreate, $libpetsc), PetscErrorCode, (MPI.MPI_Comm, Ptr{CKSP}), comm, ksp)
89-
end
90-
if comm == MPI.COMM_SELF
91-
finalizer(destroy, ksp)
92-
end
93-
return ksp
94-
end
95-
96-
function destroy(ksp::KSP{$PetscScalar})
97-
finalized($petsclib) ||
98-
@chk ccall((:KSPDestroy, $libpetsc), PetscErrorCode, (Ptr{CKSP},), ksp)
99-
return nothing
100-
end
101-
102-
function setoperators!(ksp::KSP{$PetscScalar}, A::AbstractMat{$PetscScalar}, P::AbstractMat{$PetscScalar})
103-
@chk ccall((:KSPSetOperators, $libpetsc), PetscErrorCode, (CKSP, CMat, CMat), ksp, A, P)
104-
ksp._A = A
105-
ksp._P = P
106-
return nothing
107-
end
108-
109134
function (::Fn_KSPComputeRHS{$PetscScalar})(
110135
new_ksp_ptr::CKSP,
111136
cb::CVec,
@@ -194,12 +219,6 @@ struct Fn_KSPComputeOperators{T} end
194219
return nothing
195220
end
196221
197-
function setfromoptions!(ksp::KSP{$PetscScalar})
198-
with(ksp.opts) do
199-
@chk ccall((:KSPSetFromOptions, $libpetsc), PetscErrorCode, (CKSP,), ksp)
200-
end
201-
end
202-
203222
function gettype(ksp::KSP{$PetscScalar})
204223
t_r = Ref{CKSPType}()
205224
@chk ccall((:KSPGetType, $libpetsc), PetscErrorCode, (CKSP, Ptr{CKSPType}), ksp, t_r)
@@ -227,14 +246,6 @@ struct Fn_KSPComputeOperators{T} end
227246
return r_rnorm[]
228247
end
229248
230-
function solve!(x::AbstractVec{$PetscScalar}, ksp::KSP{$PetscScalar}, b::AbstractVec{$PetscScalar})
231-
with(ksp.opts) do
232-
@chk ccall((:KSPSolve, $libpetsc), PetscErrorCode,
233-
(CKSP, CVec, CVec), ksp, b, x)
234-
end
235-
return x
236-
end
237-
238249
function solve!(ksp::KSP{$PetscScalar})
239250
with(ksp.opts) do
240251
@chk ccall((:KSPSolve, $libpetsc), PetscErrorCode,
@@ -266,21 +277,6 @@ function LinearAlgebra.ldiv!(x::AbstractVector{T}, ksp::KSPAT{T, LT}, b::Abstrac
266277
end
267278
Base.:\(ksp::KSPAT{T, LT}, b::AbstractVector{T}) where {T, LT} = ldiv!(similar(b), ksp, b)
268279
269-
270-
"""
271-
KSP(A, P; options...)
272-
273-
Construct a PETSc Krylov subspace solver.
274-
275-
Any PETSc options prefixed with `ksp_` and `pc_` can be passed as keywords.
276-
"""
277-
function KSP(A::AbstractMat{T}, P::AbstractMat{T}=A; kwargs...) where {T}
278-
ksp = KSP{T}(getcomm(A); kwargs...)
279-
setoperators!(ksp, A, P)
280-
setfromoptions!(ksp)
281-
return ksp
282-
end
283-
284280
"""
285281
KSP(da::AbstractDM; options...)
286282
@@ -300,7 +296,6 @@ end
300296
301297
Base.show(io::IO, ksp::KSP) = _show(io, ksp)
302298
303-
304299
"""
305300
iters(ksp::KSP)
306301
@@ -311,7 +306,6 @@ $(_doc_external("KSP/KSPGetIterationNumber"))
311306
"""
312307
iters
313308
314-
315309
"""
316310
resnorm(ksp::KSP)
317311

src/options.jl

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ mutable struct Options{T} <: AbstractOptions{T}
7777
ptr::CPetscOptions
7878
end
7979

80-
function Options(petsclib::PetscLibType)
80+
function Options_(petsclib::PetscLibType)
8181
@assert initialized(petsclib)
8282
PetscLib = typeof(petsclib)
8383
opts = Options{PetscLib}(C_NULL)
@@ -86,9 +86,10 @@ function Options(petsclib::PetscLibType)
8686
return opts
8787
end
8888

89-
Options(petsclib; kwargs...) = Options(petsclib, kwargs...)
90-
function Options(petsclib, ps::Pair...)
91-
opts = Options(petsclib)
89+
Options(petsclib::PetscLibType; kwargs...) = Options_(petsclib, kwargs...)
90+
Options(PetscLib::Type{<:PetscLibType}; kwargs...) = Options_(getlib(PetscLib), kwargs...)
91+
function Options_(petsclib::PetscLibType, ps::Pair...)
92+
opts = Options_(petsclib)
9293
for (k, v) in ps
9394
opts[k] = v
9495
end

src/sys.jl

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
const CPetscObject = Ptr{Cvoid}
22

3-
const UnionPetscTypes = Union{Options, AbstractVec, AbstractMat}
3+
const UnionPetscTypes = Union{Options, AbstractVec, AbstractMat, AbstractKSP}
44

55
# allows us to pass PETSc_XXX objects directly into CXXX ccall signatures
66
Base.cconvert(::Type{CPetscObject}, obj::UnionPetscTypes) = obj
@@ -12,7 +12,8 @@ function Base.unsafe_convert(::Type{Ptr{CPetscObject}}, obj::UnionPetscTypes)
1212
end
1313

1414
function getcomm(
15-
obj::Union{AbstractVec{PetscLib}, AbstractMat{PetscLib}},
15+
obj::Union{AbstractVec{PetscLib}, AbstractMat{PetscLib},
16+
AbstractKSP{PetscLib}},
1617
) where {PetscLib}
1718
comm = MPI.Comm()
1819
LibPETSc.PetscObjectGetComm(PetscLib, obj, comm)

src/vec.jl

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -612,3 +612,10 @@ function getpetsctype(vec::AbstractVec{PetscLib}) where {PetscLib}
612612
LibPETSc.VecGetType(PetscLib, vec, name_r)
613613
return unsafe_string(name_r[])
614614
end
615+
616+
function Base.similar(v::AbstractVec{PetscLib}) where {PetscLib}
617+
r_x = Ref{CVec}()
618+
LibPETSc.VecDuplicate(PetscLib, v, r_x)
619+
x = VecPtr(PetscLib, r_x[], true)
620+
return x
621+
end

test/ksp.jl

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
using Test
2+
using MPI
3+
MPI.Initialized() || MPI.Init()
4+
using PETSc
5+
using LinearAlgebra: mul!
6+
7+
@testset "KSP" begin
8+
comm = MPI.COMM_WORLD
9+
mpisize = MPI.Comm_size(comm)
10+
mpirank = MPI.Comm_rank(comm)
11+
12+
for petsclib in PETSc.petsclibs
13+
PETSc.initialize(petsclib)
14+
PetscScalar = petsclib.PetscScalar
15+
PetscInt = petsclib.PetscInt
16+
17+
loc_num_rows = 10
18+
loc_num_cols = 10
19+
diag_nonzeros = 3
20+
off_diag_non_zeros = 3
21+
22+
A = PETSc.MatAIJ(
23+
petsclib,
24+
comm,
25+
loc_num_rows,
26+
loc_num_cols,
27+
diag_nonzeros,
28+
off_diag_non_zeros,
29+
)
30+
31+
# Get compatible vectors
32+
(x, b) = PETSc.createvecs(A)
33+
34+
row_rng = PETSc.ownershiprange(A, false)
35+
for i in row_rng
36+
if i == 0
37+
vals = [-2, 1]
38+
row0idxs = [i]
39+
col0idxs = [i, i + 1]
40+
elseif i == mpisize * loc_num_rows - 1
41+
vals = [-2, 1]
42+
row0idxs = [i]
43+
col0idxs = [i, i - 1]
44+
else
45+
vals = [1, -2, 1]
46+
row0idxs = [i]
47+
col0idxs = [i - 1, i, i + 1]
48+
end
49+
PETSc.setvalues!(
50+
A,
51+
PetscInt.(row0idxs),
52+
PetscInt.(col0idxs),
53+
PetscScalar.(vals),
54+
)
55+
x[i + 1] = (i + 1)^3
56+
end
57+
PETSc.assemble!(A)
58+
PETSc.assemble!(x)
59+
60+
mul!(b, A, x)
61+
y = similar(x)
62+
63+
ksp = PETSc.KSP(A; ksp_rtol = 1e-16, pc_type = "jacobi")
64+
PETSc.solve!(y, ksp, b)
65+
PETSc.withlocalarray!(x, y) do x, y
66+
@test x y
67+
end
68+
69+
# PETSc.destroy(ksp)
70+
PETSc.destroy(A)
71+
PETSc.destroy(x)
72+
PETSc.destroy(y)
73+
PETSc.destroy(b)
74+
PETSc.finalize(petsclib)
75+
end
76+
end

test/runtests.jl

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ using MPI: mpiexec
33

44
# Do the MPI tests first so we do not have mpi running inside MPI
55
@testset "mpi tests" begin
6-
for file in ("mpivec.jl", "mpimat.jl")
6+
for file in ("mpivec.jl", "mpimat.jl", "ksp.jl")
77
@test mpiexec() do mpi_cmd
88
cmd =
99
`$mpi_cmd -n 4 $(Base.julia_cmd()) --startup-file=no --project $file`
@@ -18,3 +18,4 @@ include("options.jl")
1818
include("vec.jl")
1919
include("mat.jl")
2020
include("matshell.jl")
21+
include("ksp.jl")

0 commit comments

Comments
 (0)