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 Residual
  • bicgstab - BiConjugate Gradient Stabilized
  • richardson - Richardson iteration
  • preonly - Apply preconditioner only (for direct solvers)

Preconditioners (pc_type)

  • jacobi - Diagonal scaling
  • ilu - Incomplete LU factorization
  • lu - Direct LU factorization
  • mg - Geometric multigrid
  • gamg - Algebraic multigrid
  • none - No preconditioning

Convergence Options

  • ksp_rtol - Relative tolerance (default: 1e-5)
  • ksp_atol - Absolute tolerance
  • ksp_max_it - Maximum iterations
  • ksp_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)                        # :fieldsplit

A :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
end

The 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`.

source
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 KSP
  • prefix::String: Optional prefix for command-line options
  • options...: Additional PETSc options as keyword arguments

External Links

source
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

source
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

source
PETSc.dm — Method
dm(ksp::AbstractKSP)

The DM attached to ksp, narrowed to its flavour.

Borrowed handle

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

source
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.

Note

The new_ksp passed to ops! may not be the same as the ksp passed to set_compute_operators!.

Callback

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

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).

source
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.

Note

The new_ksp passed to rhs! may not be the same as the ksp passed to set_compute_rhs!.

Callback

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

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).

source
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

source
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

source
PETSc.solution — Method
solution(ksp::AbstractKSP)

The solution vector of ksp, as a PetscVec.

Borrowed handle

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

source
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

source
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

source
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).

Borrowed handle

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

source
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

source
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.

Callback

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

source
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.

Callback

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

source
PETSc.set_type! — Method
set_type!(p::AbstractPC, type::Symbol)

Set the preconditioner, for example :jacobi, :ilu, :gamg or :fieldsplit.

External Links

source
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

source