Skip to content

Commit 75e9e22

Browse files
committed
Save coefficients in Arnoldi struct
1 parent 7bab818 commit 75e9e22

File tree

1 file changed

+40
-45
lines changed

1 file changed

+40
-45
lines changed

src/krylov/arnoldi.rs

Lines changed: 40 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ where
1313
a: F,
1414
v: ArrayBase<S, Ix1>,
1515
ortho: Ortho,
16+
/// Coefficients
17+
h: Vec<Array1<A>>,
1618
}
1719

1820
impl<A, S, F, Ortho> Arnoldi<A, S, F, Ortho>
@@ -29,28 +31,33 @@ where
2931
let norm = v.norm_l2();
3032
azip!(mut v(&mut v) in { *v = v.div_real(norm) });
3133
ortho.append(v.view());
32-
Arnoldi { a, v, ortho }
34+
Arnoldi {
35+
a,
36+
v,
37+
ortho,
38+
h: Vec::new(),
39+
}
40+
}
41+
42+
/// Dimension of Krylov subspace
43+
pub fn dim(&self) -> usize {
44+
self.ortho.len()
3345
}
3446

3547
/// Iterate until convergent
36-
pub fn complete(self) -> (Q<A>, H<A>) {
48+
pub fn complete(mut self) -> (Q<A>, H<A>) {
49+
for _ in &mut self {} // execute iteration until convergent
3750
let q = self.ortho.get_q();
38-
let hs: Vec<Array1<A>> = self.collect();
39-
let n = hs.len();
51+
let n = self.dim();
4052
let mut h = Array2::zeros((n, n).f());
41-
for (i, hc) in hs.iter().enumerate() {
53+
for (i, hc) in self.h.iter().enumerate() {
4254
let m = std::cmp::max(n, i + 1);
4355
for j in 0..m {
4456
h[(j, i)] = hc[j];
4557
}
4658
}
4759
(q, h)
4860
}
49-
50-
/// Dimension of Krylov subspace
51-
pub fn krylov_dimension(&self) -> usize {
52-
self.ortho.len()
53-
}
5461
}
5562

5663
impl<A, S, F, Ortho> Iterator for Arnoldi<A, S, F, Ortho>
@@ -69,57 +76,45 @@ where
6976
if result.is_dependent() {
7077
None
7178
} else {
72-
Some(result.into_coeff())
79+
let coef = result.into_coeff();
80+
self.h.push(coef.clone());
81+
Some(coef)
7382
}
7483
}
7584
}
7685

77-
pub fn arnoldi_householder<A, S1, S2>(
78-
a: ArrayBase<S1, Ix2>,
79-
v: ArrayBase<S2, Ix1>,
80-
tol: A::Real,
81-
) -> impl Iterator<Item = Array1<A>>
86+
/// Interpret a matrix as a linear operator
87+
pub fn mul_mat<A, S1, S2>(a: ArrayBase<S1, Ix2>) -> impl Fn(&mut ArrayBase<S2, Ix1>)
8288
where
83-
A: Scalar + Lapack,
89+
A: Scalar,
8490
S1: Data<Elem = A>,
8591
S2: DataMut<Elem = A>,
8692
{
8793
let (n, m) = a.dim();
8894
assert_eq!(n, m, "Input matrix must be square");
89-
assert_eq!(m, v.len(), "Input matrix and vector sizes mismach");
90-
91-
let householder = Householder::new(n, tol);
92-
Arnoldi::new(
93-
move |x| {
94-
let ax = a.dot(x);
95-
azip!(mut x(x), ax in { *x = ax });
96-
},
97-
v,
98-
householder,
99-
)
95+
move |x| {
96+
assert_eq!(m, x.len(), "Input matrix and vector sizes mismatch");
97+
let ax = a.dot(x);
98+
azip!(mut x(x), ax in { *x = ax });
99+
}
100100
}
101101

102-
pub fn arnoldi_mgs<A, S1, S2>(
103-
a: ArrayBase<S1, Ix2>,
104-
v: ArrayBase<S2, Ix1>,
105-
tol: A::Real,
106-
) -> impl Iterator<Item = Array1<A>>
102+
pub fn arnoldi_householder<A, S1, S2>(a: ArrayBase<S1, Ix2>, v: ArrayBase<S2, Ix1>, tol: A::Real) -> (Q<A>, H<A>)
107103
where
108104
A: Scalar + Lapack,
109105
S1: Data<Elem = A>,
110106
S2: DataMut<Elem = A>,
111107
{
112-
let (n, m) = a.dim();
113-
assert_eq!(n, m, "Input matrix must be square");
114-
assert_eq!(m, v.len(), "Input matrix and vector sizes mismach");
108+
let householder = Householder::new(v.len(), tol);
109+
Arnoldi::new(mul_mat(a), v, householder).complete()
110+
}
115111

116-
let mgs = MGS::new(n, tol);
117-
Arnoldi::new(
118-
move |x| {
119-
let ax = a.dot(x);
120-
azip!(mut x(x), ax in { *x = ax });
121-
},
122-
v,
123-
mgs,
124-
)
112+
pub fn arnoldi_mgs<A, S1, S2>(a: ArrayBase<S1, Ix2>, v: ArrayBase<S2, Ix1>, tol: A::Real) -> (Q<A>, H<A>)
113+
where
114+
A: Scalar + Lapack,
115+
S1: Data<Elem = A>,
116+
S2: DataMut<Elem = A>,
117+
{
118+
let mgs = MGS::new(v.len(), tol);
119+
Arnoldi::new(mul_mat(a), v, mgs).complete()
125120
}

0 commit comments

Comments
 (0)