Skip to content

Commit a7543f5

Browse files
committed
Do not manage R matrix in MGS
1 parent 86b650b commit a7543f5

File tree

1 file changed

+34
-38
lines changed

1 file changed

+34
-38
lines changed

src/arnoldi.rs

Lines changed: 34 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,51 +1,44 @@
11
use crate::{generate::*, inner::*, norm::Norm, types::*};
22
use ndarray::*;
3-
use num_traits::Zero;
43

4+
/// Iterative orthogonalizer using modified Gram-Schmit procedure
55
#[derive(Debug, Clone)]
66
pub struct MGS<A> {
7-
dim: usize,
7+
/// Dimension of base space
8+
dimension: usize,
9+
/// Basis of spanned space
810
q: Vec<Array1<A>>,
9-
r: Vec<Array1<A>>,
1011
}
1112

12-
pub enum Dependence<A: Scalar> {
13-
Orthogonal(A::Real),
14-
Coefficient(Array1<A>),
15-
}
13+
pub type Residual<S> = ArrayBase<S, Ix1>;
14+
pub type Coefficient<A> = Array1<A>;
1615

1716
impl<A: Scalar + Lapack> MGS<A> {
18-
pub fn new(dim: usize) -> Self {
17+
pub fn new(dimension: usize) -> Self {
1918
Self {
20-
dim,
19+
dimension,
2120
q: Vec::new(),
22-
r: Vec::new(),
2321
}
2422
}
2523

2624
pub fn dim(&self) -> usize {
27-
self.dim
25+
self.dimension
2826
}
2927

3028
pub fn len(&self) -> usize {
3129
self.q.len()
3230
}
3331

34-
/// Add new vector, return residual norm
35-
pub fn append<S>(&mut self, a: ArrayBase<S, Ix1>) -> A::Real
36-
where
37-
S: Data<Elem = A>,
38-
{
39-
self.append_if(a, A::Real::zero()).unwrap()
40-
}
41-
42-
/// Add new vector if the residual is larger than relative tolerance
43-
pub fn append_if<S>(&mut self, a: ArrayBase<S, Ix1>, rtol: A::Real) -> Option<A::Real>
32+
/// Orthogonalize given vector using current basis
33+
///
34+
/// Panic
35+
/// -------
36+
/// - if the size of the input array mismaches to the dimension
37+
pub fn orthogonalize<S>(&self, mut a: ArrayBase<S, Ix1>) -> (Residual<S>, Coefficient<A>)
4438
where
45-
S: Data<Elem = A>,
39+
S: DataMut<Elem = A>,
4640
{
4741
assert_eq!(a.len(), self.dim());
48-
let mut a = a.into_owned();
4942
let mut coef = Array1::zeros(self.len() + 1);
5043
for i in 0..self.len() {
5144
let q = &self.q[i];
@@ -54,32 +47,35 @@ impl<A: Scalar + Lapack> MGS<A> {
5447
coef[i] = c;
5548
}
5649
let nrm = a.norm_l2();
50+
coef[self.len()] = A::from_real(nrm);
51+
(a, coef)
52+
}
53+
54+
/// Add new vector if the residual is larger than relative tolerance
55+
///
56+
/// Panic
57+
/// -------
58+
/// - if the size of the input array mismaches to the dimension
59+
pub fn append_if_independent<S>(&mut self, a: ArrayBase<S, Ix1>, rtol: A::Real) -> Option<Coefficient<A>>
60+
where
61+
S: Data<Elem = A>,
62+
{
63+
let a = a.into_owned();
64+
let (mut a, coef) = self.orthogonalize(a);
65+
let nrm = coef[coef.len()].re();
5766
if nrm < rtol {
67+
// Linearly dependent
5868
return None;
5969
}
60-
coef[self.len()] = A::from_real(nrm);
61-
self.r.push(coef);
6270
azip!(mut a in { *a = *a / A::from_real(nrm) });
6371
self.q.push(a);
64-
Some(nrm)
72+
Some(coef)
6573
}
6674

6775
/// Get orthogonal basis as Q matrix
6876
pub fn get_q(&self) -> Array2<A> {
6977
hstack(&self.q).unwrap()
7078
}
71-
72-
/// Get each vector norm and coefficients as R matrix
73-
pub fn get_r(&self) -> Array2<A> {
74-
let len = self.len();
75-
let mut r = Array2::zeros((len, len));
76-
for i in 0..len {
77-
for j in 0..=i {
78-
r[(j, i)] = self.r[i][j];
79-
}
80-
}
81-
r
82-
}
8379
}
8480

8581
#[cfg(test)]

0 commit comments

Comments
 (0)