1313
1414"""
1515```julia
16- partialschur(A; nev, which, tol, mindim, maxdim, restarts) → PartialSchur, History
16+ partialschur(A; v1, workspace, nev, which, tol, mindim, maxdim, restarts) → PartialSchur, History
1717```
1818
1919Find `nev` approximate eigenpairs of `A` with eigenvalues near a specified target.
@@ -33,6 +33,7 @@ The most important keyword arguments:
3333| `nev` | `Int` | `min(6, size(A, 1))` |Number of eigenvalues |
3434| `which` | `Symbol` or `Target` | `:LM` | One of `:LM`, `:LR`, `:SR`, `:LI`, `:SI`, see below. |
3535| `tol` | `Real` | `√eps` | Tolerance for convergence: ‖Ax - xλ‖₂ < tol * ‖λ‖ |
36+ | `v1` | `AbstractVector` | `nothing` | Optional starting vector for the Krylov subspace |
3637
3738The target `which` can be any of:
3839
@@ -93,6 +94,7 @@ is usually about two times `mindim`.
9394"""
9495function partialschur (
9596 A;
97+ v1:: Union{AbstractVector,Nothing} = nothing ,
9698 nev:: Int = min (6 , size (A, 1 )),
9799 which:: Union{Target,Symbol} = LM (),
98100 tol:: Real = sqrt (eps (real (vtype (A)))),
@@ -101,14 +103,24 @@ function partialschur(
101103 restarts:: Int = 200 ,
102104)
103105 s = checksquare (A)
104- if nev < 1
105- throw (ArgumentError (" nev cannot be less than 1" ))
106- end
106+ nev < 1 && throw (ArgumentError (" nev cannot be less than 1" ))
107107 nev ≤ mindim ≤ maxdim ≤ s || throw (
108- ArgumentError (" nev ≤ mindim ≤ maxdim does not hold, got $nev ≤ $mindim ≤ $maxdim " ),
108+ ArgumentError (
109+ " nev ≤ mindim ≤ maxdim ≤ size(A, 1) does not hold, got $nev ≤ $mindim ≤ $maxdim ≤ $s " ,
110+ ),
109111 )
110112 _which = which isa Target ? which : _symbol_to_target (which)
111- _partialschur (A, vtype (A), mindim, maxdim, nev, tol, restarts, _which)
113+
114+ if v1 === nothing
115+ arnoldi = ArnoldiWorkspace (vtype (A), size (A, 1 ), maxdim)
116+ reinitialize! (arnoldi, 0 , v -> rand! (v))
117+ else
118+ length (v1) == size (A, 1 ) ||
119+ throw (ArgumentError (" v1 should have the same dimension as A" ))
120+ arnoldi = ArnoldiWorkspace (v1, maxdim)
121+ reinitialize! (arnoldi, 0 , v -> copyto! (v, v1))
122+ end
123+ _partialschur (A, arnoldi, mindim, maxdim, nev, tol, restarts, _which)
112124end
113125
114126_symbol_to_target (sym:: Symbol ) =
@@ -156,33 +168,25 @@ end
156168
157169function _partialschur (
158170 A,
159- :: Type {T} ,
171+ arnoldi :: ArnoldiWorkspace {T} ,
160172 mindim:: Int ,
161173 maxdim:: Int ,
162174 nev:: Int ,
163175 tol:: Ttol ,
164176 restarts:: Int ,
165177 which:: Target ,
166178) where {T,Ttol<: Real }
167- n = size (A, 1 )
168-
169- # Pre-allocated Arnoldi decomp
170- arnoldi = Arnoldi {T} (n, maxdim)
171-
172179 # Unpack for convenience
173180 H = arnoldi. H
174181 V = arnoldi. V
182+ Vtmp = arnoldi. V_tmp
183+ Q = arnoldi. Q
175184
176- # For a change of basis we have Vtmp as working space
177- Vtmp = Matrix {T} (undef, n, maxdim)
178-
179- # Unitary matrix used for change of basis of V.
180- Q = Matrix {T} (undef, maxdim, maxdim)
181-
182- # We only need to store one eignvector of the Hessenberg matrix
185+ # We only need to store one eigenvector of the Hessenberg matrix.
183186 x = zeros (complex (T), maxdim)
184187
185188 # And we store the reflector to transform H back to Hessenberg separately
189+ # TODO : can be in-place in H now.
186190 G = Reflector {T} (maxdim)
187191
188192 # Approximate residual norms for all Ritz values, and Ritz values
@@ -205,7 +209,6 @@ function _partialschur(
205209 prods = mindim
206210
207211 # Initialize an Arnoldi relation of size `mindim`
208- reinitialize! (arnoldi)
209212 iterate_arnoldi! (A, arnoldi, 1 : mindim)
210213
211214 for iter = 1 : restarts
0 commit comments