1313 a : F ,
1414 v : ArrayBase < S , Ix1 > ,
1515 ortho : Ortho ,
16+ /// Coefficients
17+ h : Vec < Array1 < A > > ,
1618}
1719
1820impl < 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
5663impl < 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 > )
8288where
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 > )
107103where
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