pub enum Preconditioner {
Identity,
Jacobi(JacobiPreconditioner),
Ilu0(Ilu0Preconditioner),
}Expand description
Preconditioner M^{-1} ≈ A^{-1}, dispatched by enum (no trait objects).
A preconditioner turns a residual r into z = M^{-1} r, an approximate
error, which the Krylov solvers use to accelerate convergence. Construct one
from the system matrix with Preconditioner::jacobi or
Preconditioner::ilu0, or use Preconditioner::identity for none.
Variants§
Identity
No preconditioning: M = I, so z = r.
Jacobi(JacobiPreconditioner)
Diagonal (Jacobi) scaling: z = r / diag(A).
Ilu0(Ilu0Preconditioner)
ILU(0) incomplete factorisation: z = (LU)^{-1} r.
Implementations§
Source§impl Preconditioner
impl Preconditioner
Sourcepub fn jacobi(a: &LduMatrix) -> Self
pub fn jacobi(a: &LduMatrix) -> Self
Build a Jacobi (reciprocal-diagonal) preconditioner from a.
Cannot break down: a zero diagonal entry is treated as 1.0. The
guaranteed-robust choice when ILU(0) is not warranted.
Sourcepub fn ilu0(a: &LduMatrix) -> Self
pub fn ilu0(a: &LduMatrix) -> Self
Build an ILU(0) preconditioner from a (same sparsity pattern as A).
A genuine incomplete LU factorisation with a small-pivot guard; see
Ilu0Preconditioner. Typically far stronger than Jacobi on
diagonally-dominant / mildly ill-conditioned systems.
Sourcepub fn apply(&self, r: &[f64], z: &mut [f64])
pub fn apply(&self, r: &[f64], z: &mut [f64])
Apply the preconditioner serially: write z = M^{-1} r.
r and z must both have length n_cells. For Preconditioner::Identity
this copies r into z. Equivalent to Self::apply_on with
ComputeBackend::Serial.
Sourcepub fn apply_on(&self, r: &[f64], z: &mut [f64], backend: ComputeBackend)
pub fn apply_on(&self, r: &[f64], z: &mut [f64], backend: ComputeBackend)
Apply the preconditioner on the chosen ComputeBackend: write
z = M^{-1} r.
§How much each variant actually parallelises
| Variant | Backend honoured? | Why |
|---|---|---|
Identity | no — copy_from_slice | already a single memcpy; there is nothing to thread |
Jacobi | yes | one independent multiply per cell — embarrassingly parallel |
Ilu0 | no — always serial | the triangular solves have a loop-carried dependence; see Ilu0Preconditioner::apply_on |
This table is the honest answer to “did the preconditioners move onto the backend?”: one of the three did, and the reason the other two did not is structural rather than unfinished work.
§Determinism
All three variants are bitwise identical across backends and thread
counts, and bitwise identical to Self::apply. Two are serial anyway,
and Jacobi is element-wise, so no summation is reassociated. A caller may
therefore switch backend without perturbing a solver’s iteration count or
residual history through the preconditioner.
§Arguments
r— residual to precondition, lengthn_cells.z— output buffer, lengthn_cells. Fully overwritten.backend— requested execution backend.