KSP
The KSP (Krylov Subspace Methods) module provides iterative linear solvers for systems of the form Ax = b. PETSc offers a wide variety of Krylov methods and preconditioners.
Overview
KSP provides:
- Krylov methods: GMRES, CG, BiCGStab, and many more
- Preconditioners: Jacobi, ILU, multigrid, direct solvers, etc.
- Runtime configuration: Choose methods via command-line options
- Convergence monitoring: Built-in residual tracking
Creating a KSP Solver
From a Matrix
# Basic creation with default options. The communicator comes from `A`
ksp = KSP(A)
# With the preconditioner construction matrix P
ksp = KSP(A, P)
# With options
ksp = KSP(A;
ksp_type = "gmres",
pc_type = "ilu",
ksp_rtol = 1e-8
)From a DM
# Create KSP associated with a DM (for multigrid, etc.)
ksp = KSP(dm;
ksp_type = "cg",
pc_type = "mg"
)From a Sparse Matrix
# Directly from Julia SparseMatrixCSC
using SparseArrays
S = sprand(100, 100, 0.1) + 10I
ksp = KSP(petsclib, MPI.COMM_SELF, S)Solving
# Solve Ax = b, writing into x. The written vector comes first
PETSc.solve!(x, ksp, b)
# `ldiv!` and `\` are the LinearAlgebra spellings of the same call
using LinearAlgebra
ldiv!(x, ksp, b)
x = ksp \ b
# What PETSc did
PETSc.type_name(ksp) # :gmres, a Symbol
PETSc.converged_reason(ksp) # positive when it converged
PETSc.iteration_number(ksp)
PETSc.destroy!(ksp)KSP is the type, not a factory function: ksp isa PETSc.KSP holds, and PETSc.dm(ksp) hands back the DM it was built on as a borrowed handle — destroy! on it is a no-op (naming conventions, §3.3).
Type names are Symbol at the Julia API: PETSc.set_type!(ksp, :cg) and PETSc.type_name(ksp) === :cg. The String spelling warns in v0.5 and is a MethodError in v0.6 (§3.1).
A nested solver
An inner solve, such as the Schur complement solve inside a preconditioner, starts from a bare KSP and an assembled operator. An options prefix keeps its options apart from the outer solver's:
inner = LibPETSc.KSPCreate(petsclib, comm)
PETSc.set_operators!(inner, S) # S also builds the preconditioner; pass P to differ
PETSc.set_options_prefix!(inner, "schur_") # reads -schur_ksp_type, -schur_pc_type, ...
PETSc.set_from_options!(inner) # apply them now rather than at the first solve!
PETSc.solve!(y, inner, r)
PETSc.options_prefix(inner) # "schur_"A KSP built on a DM computes its operator, right-hand side and initial guess from it. PETSc.set_dm_active!(ksp, false) keeps the DM for its geometry (multigrid needs it) and takes the rest from set_operators! and solve!; PETSc.set_dm_active!(ksp, :rhs, false) switches off one part.
Common Solver/Preconditioner Options
Krylov Methods (ksp_type)
cg- Conjugate Gradient (symmetric positive definite)gmres- Generalized Minimum Residualbicgstab- BiConjugate Gradient Stabilizedrichardson- Richardson iterationpreonly- Apply preconditioner only (for direct solvers)
Preconditioners (pc_type)
jacobi- Diagonal scalingilu- Incomplete LU factorizationlu- Direct LU factorizationmg- Geometric multigridgamg- Algebraic multigridnone- No preconditioning
Convergence Options
ksp_rtol- Relative tolerance (default: 1e-5)ksp_atol- Absolute toleranceksp_max_it- Maximum iterationsksp_monitor- Print residual each iteration
Example: Multigrid Solver
ksp = KSP(dm;
ksp_type = "cg",
pc_type = "mg",
pc_mg_levels = 4,
pc_mg_galerkin = true,
mg_levels_ksp_type = "richardson",
mg_levels_pc_type = "jacobi",
mg_coarse_pc_type = "lu"
)The preconditioner
PETSc.pc(ksp) hands back the preconditioner as a borrowed LibPETSc.PC. It takes the same set_type!/type_name pair as the solver, and is how a split preconditioner gets its index sets, which options alone cannot supply:
p = PETSc.pc(ksp) # not pc = pc(ksp), see naming.md §3.2
PETSc.set_type!(p, :fieldsplit)
PETSc.set_fieldsplit_is!(p, "u", is_u) # rows of the first split, 0-based
PETSc.set_fieldsplit_is!(p, "p", is_p) # options prefix -fieldsplit_p_
PETSc.type_name(p) # :fieldsplitA :shell preconditioner is written in Julia. The action writes into its first argument, like every other callback here:
p = PETSc.pc(ksp)
PETSc.set_type!(p, :shell)
PETSc.set_shell_setup!(p) do p
# rebuild whatever apply! needs, e.g. after the operator changed
end
PETSc.set_shell_apply!(p) do y, p, x
PETSc.with_local_array!(y, x; read = (false, true), write = (true, false)) do ya, xa
ya .= xa ./ diagonal # Jacobi, by hand
end
endThe closures are kept with the PETSc preconditioner, not with the wrapper p, so p can be dropped. An exception thrown inside either one comes out of the solve that ran it, as itself: a DomainError in apply! makes ksp \ b throw that DomainError (naming conventions, §18.4).
A LibPETSc.PC is also what every low-level PC* function takes, so anything without a high-level verb is one call away: LibPETSc.PCFieldSplitSetType(petsclib, p, LibPETSc.PC_COMPOSITE_SCHUR).
Functions
PETSc.LibPETSc.KSP — Method
KSP(petsclib, comm::MPI.Comm, A::SparseMatrixCSC; options...)Create a KSP with the sparse matrix A using the petsclib. If petsclib is not given, the default library will be used`.
PETSc.LibPETSc.KSP — Method
KSP(dm::AbstractPetscDM; prefix="", options...)Create a KSP associated with the dm with optional prefix and options.
The options are applied here, once, through KSPSetFromOptions. A setting made in code afterwards overrides them.
The communicator is obtained from dm. The KSP can be used with geometric multigrid when the DM provides grid hierarchy information.
Arguments
dm::AbstractPetscDM: The DM object to associate with the KSPprefix::String: Optional prefix for command-line optionsoptions...: Additional PETSc options as keyword arguments
External Links
- PETSc Manual:
KSP/KSPCreate
- PETSc Manual:
KSP/KSPSetDM
- PETSc Manual:
KSP/KSPSetFromOptions
PETSc.LibPETSc.KSP — Method
KSP(comm::MPI.Comm, A::AbstractPetscMat, P::AbstractPetscMat{PetscLib} = A; prefix="", options...)Create a KSP using the matrix A and preconditioner construction matrix P with optional prefix and options.
The options are applied here, once, through KSPSetFromOptions. A setting made in code afterwards, such as set_tolerances!, overrides them.
The communicator is obtained from A and if it has size 1 then the garbage collector is set, otherwise the user is responsible for calling destroy!.
External Links
- PETSc Manual:
KSP/KSPCreate
- PETSc Manual:
KSP/KSPSetOperators
- PETSc Manual:
KSP/KSPSetFromOptions
PETSc.converged_reason — Method
converged_reason(ksp::AbstractKSP)Why the last solve! stopped, as a LibPETSc.KSPConvergedReason: positive when it converged, negative when it diverged.
External Links
- PETSc Manual:
KSP/KSPGetConvergedReason
PETSc.destroy! — Method
destroy!(ksp::KSP)Destroy the solver ksp holds. Does nothing on a borrowed handle, such as the one ksp(ts) hands back: see owns.
External Links
- PETSc Manual:
KSP/KSPDestroy
PETSc.dm — Method
dm(ksp::AbstractKSP)The DM attached to ksp, narrowed to its flavour.
The returned object is owned by the object it was asked of, not by the caller: it carries no finalizer and must not be destroyed. destroy! on it is a no-op (owns).
External Links
- PETSc Manual:
KSP/KSPGetDM
PETSc.iteration_number — Method
iteration_number(ksp::AbstractKSP)The number of iterations the last solve! took.
External Links
- PETSc Manual:
KSP/KSPGetIterationNumber
PETSc.set_compute_operators! — Function
set_compute_operators!(ops!::Function, ksp::KSP)Define ops! to be the compute operators function for the ksp. A call to ops!(A, P, new_ksp) should set the elements of the PETSc matrix linear operator A and preconditioning matrix P based on the new_ksp.
The closure is kept with the PETSc object, not with the wrapper passed here, so a borrowed handle is fine to pass. It succeeds by returning and fails by throwing; its return value is ignored, except that a nonzero Integer still fails the call and warns until v0.6. An exception it throws comes out of the solve!, step! or setup! that ran it.
External Links
- PETSc Manual:
KSP/KSPSetComputeOperators
The callback comes first (docs/src/man/naming.md §8.1), so do block syntax works. v0.4 also accepted the subject-first order; that method is gone in v0.5, and there is no shim for it (§16).
PETSc.set_compute_rhs! — Function
set_compute_rhs!(rhs!::Function, ksp::AbstractKSP)Define rhs! to be the right-hand side function of the ksp. A call to rhs!(b, new_ksp) should set the elements of the PETSc vector b based on the new_ksp.
The closure is kept with the PETSc object, not with the wrapper passed here, so a borrowed handle is fine to pass. It succeeds by returning and fails by throwing; its return value is ignored, except that a nonzero Integer still fails the call and warns until v0.6. An exception it throws comes out of the solve!, step! or setup! that ran it.
External Links
- PETSc Manual:
KSP/KSPSetComputeRHS
The callback comes first (docs/src/man/naming.md §8.1), so do block syntax works. v0.4 also accepted the subject-first order; that method is gone in v0.5, and there is no shim for it (§16).
PETSc.set_dm_active! — Method
set_dm_active!(ksp::AbstractKSP, flag::Bool)
set_dm_active!(ksp::AbstractKSP, part::Symbol, flag::Bool)Whether the DM attached to ksp computes its operator, right-hand side and initial guess. The first form sets all three; the second sets one, part being :operator, :rhs or :initial_guess (:all is the first form). With false, ksp keeps the DM for its geometry, for example for multigrid, while set_operators! and solve! supply the rest. Returns ksp.
External Links
- PETSc Manual:
KSP/KSPSetDMActive
PETSc.set_operators! — Method
set_operators!(ksp::AbstractKSP, A::AbstractPetscMat, P::AbstractPetscMat = A)Solve with the operator A, building the preconditioner from P. Returns ksp.
ksp takes a reference to both matrices, so they stay valid inside it after the caller destroys its own handles.
External Links
- PETSc Manual:
KSP/KSPSetOperators
PETSc.set_type! — Method
set_type!(ksp::AbstractKSP, type::Symbol)Set the Krylov method, for example :gmres, :cg or :preonly.
External Links
- PETSc Manual:
KSP/KSPSetType
PETSc.solution — Method
solution(ksp::AbstractKSP)The solution vector of ksp, as a PetscVec.
The returned object is owned by the object it was asked of, not by the caller: it carries no finalizer and must not be destroyed. destroy! on it is a no-op (owns).
External Links
- PETSc Manual:
KSP/KSPGetSolution
PETSc.type_name — Method
type_name(ksp::AbstractKSP)The name PETSc knows this solver by, as a Symbol (:gmres, :cg, …), or nothing when no type has been set yet (docs/src/man/naming.md §3.1). v0.4 answered with a String; that is a break with no shim (§16).
External Links
- PETSc Manual:
KSP/KSPGetType
PETSc.destroy! — Method
destroy!(p::AbstractPC)Destroy the preconditioner p holds. Does nothing on the borrowed handle pc hands back, which its KSP destroys: see owns.
External Links
- PETSc Manual:
PC/PCDestroy
PETSc.pc — Method
pc(ksp::AbstractKSP)The preconditioner ksp applies. Inside the package, bind it as p = pc(ksp), not pc = pc(ksp) (docs/src/man/naming.md §3.2).
The returned object is owned by the object it was asked of, not by the caller: it carries no finalizer and must not be destroyed. destroy! on it is a no-op (owns).
External Links
- PETSc Manual:
KSP/KSPGetPC
PETSc.set_fieldsplit_is! — Method
set_fieldsplit_is!(p::AbstractPC, name::AbstractString, is::AbstractIS)Define the split called name of a :fieldsplit preconditioner as the rows listed in is, which holds global, 0-based indices. Call it once per split, in the order the splits should have; name is also the options prefix of the split's solver (-fieldsplit_<name>_ksp_type).
Throws an ArgumentError unless p is already of type :fieldsplit: PETSc would otherwise ignore the call without saying so.
External Links
- PETSc Manual:
PC/PCFieldSplitSetIS
PETSc.set_shell_apply! — Function
set_shell_apply!(apply!, p::AbstractPC)Make apply! the action of the :shell preconditioner p. It is called as apply!(y, p, x) and writes the preconditioned x into y. Returns p.
Throws an ArgumentError unless p is already of type :shell: PETSc would otherwise ignore the call without saying so.
The callback comes first (docs/src/man/naming.md §8.1), so do block syntax works.
The closure is kept with the PETSc object, not with the wrapper passed here, so a borrowed handle is fine to pass. It succeeds by returning and fails by throwing; its return value is ignored, except that a nonzero Integer still fails the call and warns until v0.6. An exception it throws comes out of the solve!, step! or setup! that ran it.
External Links
- PETSc Manual:
PC/PCShellSetApply
PETSc.set_shell_setup! — Function
set_shell_setup!(setup!, p::AbstractPC)Make setup! the setup step of the :shell preconditioner p, called as setup!(p) whenever PETSc sets the preconditioner up, for example after the operator changes. The :shell requirement is as for set_shell_apply!. Returns p.
The callback comes first (docs/src/man/naming.md §8.1), so do block syntax works.
The closure is kept with the PETSc object, not with the wrapper passed here, so a borrowed handle is fine to pass. It succeeds by returning and fails by throwing; its return value is ignored, except that a nonzero Integer still fails the call and warns until v0.6. An exception it throws comes out of the solve!, step! or setup! that ran it.
External Links
- PETSc Manual:
PC/PCShellSetSetUp
PETSc.set_type! — Method
set_type!(p::AbstractPC, type::Symbol)Set the preconditioner, for example :jacobi, :ilu, :gamg or :fieldsplit.
External Links
- PETSc Manual:
PC/PCSetType
PETSc.type_name — Method
type_name(p::AbstractPC)The name PETSc knows this preconditioner by, as a Symbol (:jacobi, :ilu, :fieldsplit, …), or nothing when no type has been set yet.
External Links
- PETSc Manual:
PC/PCGetType