1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
use super::error::BandedError;
/// High-level policy for selecting a native linear solver backend.
///
/// For compact banded matrices, [`LinearSolverPolicy::Auto`] and
/// [`LinearSolverPolicy::ForceBanded`] use the faithful LAPACK-style banded LU
/// implementation. The dense general-pivot backend is kept as an explicit
/// diagnostic/legacy choice rather than a default path.
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum LinearSolverPolicy {
Auto,
ForceBlockTridiagonal,
ForceBlockTridiagonalConsistent,
ForceBanded,
ForceGeneralBandedPartialPivot,
ForceFaerSparse,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum FallbackPolicy {
Never,
ToFaerSparse,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct LinearSolverConfig {
/// Backend-selection policy.
pub policy: LinearSolverPolicy,
/// Optional fallback when the preferred native backend cannot factorize.
pub fallback: FallbackPolicy,
/// Guarded iterative-refinement attempts after the direct solve.
///
/// The default is `0`: the faithful LAPACK-style banded solver already
/// mirrors `DGBTRF`/`DGBTRS`, and current BVP workloads do not benefit from
/// an unconditional extra refinement pass. Turn this on only for targeted
/// experiments.
pub iterative_refinement_steps: usize,
}
impl Default for LinearSolverConfig {
fn default() -> Self {
Self {
policy: LinearSolverPolicy::Auto,
fallback: FallbackPolicy::ToFaerSparse,
iterative_refinement_steps: 0,
}
}
}
impl LinearSolverConfig {
/// Default automatic policy.
///
/// On a [`BandedAssembly`](crate::somelinalg::banded::BandedAssembly) this
/// resolves to the faithful LAPACK-style banded LU backend with no
/// refinement. On structured block-tridiagonal input it keeps using the
/// structured native policy.
pub fn auto() -> Self {
Self::default()
}
/// Forces the faithful LAPACK-style banded LU backend.
///
/// This is the recommended default whenever the input is a general compact
/// banded matrix rather than a known block-tridiagonal chain.
pub fn faithful_banded() -> Self {
Self {
policy: LinearSolverPolicy::ForceBanded,
fallback: FallbackPolicy::ToFaerSparse,
iterative_refinement_steps: 0,
}
}
/// Forces faithful banded LU and enables guarded iterative refinement.
///
/// Prefer [`Self::faithful_banded`] for production defaults; this helper is
/// mainly for diagnostics and solver-comparison tables.
pub fn faithful_banded_with_refinement(iterative_refinement_steps: usize) -> Self {
Self {
iterative_refinement_steps,
..Self::faithful_banded()
}
}
/// Returns a copy with a different guarded-refinement budget.
pub fn with_iterative_refinement_steps(mut self, iterative_refinement_steps: usize) -> Self {
self.iterative_refinement_steps = iterative_refinement_steps;
self
}
}
#[derive(Debug)]
pub enum LinearSolveError {
Native(BandedError),
Faer(String),
InvalidPolicy(&'static str),
}
impl From<BandedError> for LinearSolveError {
fn from(value: BandedError) -> Self {
Self::Native(value)
}
}