47 using Index = Eigen::Index;
48 using Complex = std::complex<Scalar>;
49 using Matrix = Eigen::Matrix<Scalar, Eigen::Dynamic, Eigen::Dynamic>;
50 using ComplexVector = Eigen::Matrix<Complex, Eigen::Dynamic, 1>;
55 static bool is_complex(
const Complex& v) {
return v.imag() != Scalar(0); }
56 static bool is_conj(
const Complex& v1,
const Complex& v2) {
return v1 == Eigen::numext::conj(v2); }
60 static void run(
const ComplexVector& ritz_val, Index k, ArnoldiFac& fac, Matrix& Q)
64 const Index ncv = ritz_val.size();
65 DoubleShiftQR<Scalar> decomp_ds(ncv);
66 UpperHessenbergQR<Scalar> decomp_hb(ncv);
68 for (Index i = k; i < ncv; i++)
70 if (is_complex(ritz_val[i]) && is_conj(ritz_val[i], ritz_val[i + 1]))
82 const Scalar s = Scalar(2) * ritz_val[i].real();
83 const Scalar t = norm(ritz_val[i]);
84 decomp_ds.compute(fac.matrix_H(), s, t);
87 decomp_ds.apply_YQ(Q);
92 fac.compress_H(decomp_ds);
99 decomp_hb.compute(fac.matrix_H(), ritz_val[i].real());
102 decomp_hb.apply_YQ(Q);
104 fac.compress_H(decomp_hb);
155 using Scalar =
typename OpType::Scalar;
159 using RealScalar =
typename Eigen::NumTraits<Scalar>::Real;
161 using Complex = std::complex<RealScalar>;
162 using Index = Eigen::Index;
163 using Matrix = Eigen::Matrix<Scalar, Eigen::Dynamic, Eigen::Dynamic>;
164 using Vector = Eigen::Matrix<Scalar, Eigen::Dynamic, 1>;
165 using ComplexMatrix = Eigen::Matrix<Complex, Eigen::Dynamic, Eigen::Dynamic>;
166 using ComplexVector = Eigen::Matrix<Complex, Eigen::Dynamic, 1>;
167 using RealArray = Eigen::Array<RealScalar, Eigen::Dynamic, 1>;
168 using BoolArray = Eigen::Array<bool, Eigen::Dynamic, 1>;
169 using MapMat = Eigen::Map<Matrix>;
170 using MapVec = Eigen::Map<Vector>;
171 using MapConstVec = Eigen::Map<const Vector>;
173 using ArnoldiOpType = ArnoldiOp<OpType, BOpType>;
174 using ArnoldiFac = Arnoldi<ArnoldiOpType>;
188 ComplexVector m_ritz_val;
189 ComplexMatrix m_ritz_vec;
190 ComplexVector m_ritz_est;
193 BoolArray m_ritz_conv;
200 static bool is_complex(
const Complex& v) {
return v.imag() != Scalar(0); }
201 static bool is_conj(
const Complex& v1,
const Complex& v2) {
return v1 == Eigen::numext::conj(v2); }
204 void restart(Index k,
SortRule selection)
212 Matrix Q = Matrix::Identity(m_ncv, m_ncv);
214 RestartArnoldi<Scalar, ArnoldiFac>::run(m_ritz_val, k, m_fac, Q);
219 m_fac.factorize_from(k, m_ncv, m_nmatop);
221 retrieve_ritzpair(selection);
225 Index num_converged(
const RealScalar& tol)
230 const RealScalar eps = TypeTraits<RealScalar>::epsilon();
233 const RealScalar eps23 = pow(eps, RealScalar(2) / 3);
236 RealArray thresh = tol * m_ritz_val.head(m_nev).array().abs().max(eps23);
237 RealArray resid = m_ritz_est.head(m_nev).array().abs() * m_fac.f_norm();
239 m_ritz_conv = (resid < thresh);
241 return m_ritz_conv.count();
245 Index nev_adjusted(Index nconv)
251 const RealScalar near_0 = TypeTraits<RealScalar>::min() * RealScalar(10);
253 Index nev_new = m_nev;
254 for (Index i = m_nev; i < m_ncv; i++)
255 if (abs(m_ritz_est[i]) < near_0)
259 nev_new += (std::min)(nconv, (m_ncv - nev_new) / 2);
260 if (nev_new == 1 && m_ncv >= 6)
262 else if (nev_new == 1 && m_ncv > 3)
265 if (nev_new > m_ncv - 2)
270 if (is_complex(m_ritz_val[nev_new - 1]) &&
271 is_conj(m_ritz_val[nev_new - 1], m_ritz_val[nev_new]))
280 void retrieve_ritzpair(
SortRule selection)
282 UpperHessenbergEigen<Scalar> decomp(m_fac.matrix_H());
283 const ComplexVector& evals = decomp.eigenvalues();
284 ComplexMatrix evecs = decomp.eigenvectors();
287 std::vector<Index> ind;
292 SortEigenvalue<Complex, SortRule::LargestMagn> sorting(evals.data(), m_ncv);
298 SortEigenvalue<Complex, SortRule::LargestReal> sorting(evals.data(), m_ncv);
304 SortEigenvalue<Complex, SortRule::LargestImag> sorting(evals.data(), m_ncv);
310 SortEigenvalue<Complex, SortRule::SmallestMagn> sorting(evals.data(), m_ncv);
316 SortEigenvalue<Complex, SortRule::SmallestReal> sorting(evals.data(), m_ncv);
322 SortEigenvalue<Complex, SortRule::SmallestImag> sorting(evals.data(), m_ncv);
327 throw std::invalid_argument(
"unsupported selection rule");
331 for (Index i = 0; i < m_ncv; i++)
333 m_ritz_val[i] = evals[ind[i]];
334 m_ritz_est[i] = evecs(m_ncv - 1, ind[i]);
336 for (Index i = 0; i < m_nev; i++)
338 m_ritz_vec.col(i).noalias() = evecs.col(ind[i]);
345 virtual void sort_ritzpair(
SortRule sort_rule)
347 std::vector<Index> ind;
352 SortEigenvalue<Complex, SortRule::LargestMagn> sorting(m_ritz_val.data(), m_nev);
358 SortEigenvalue<Complex, SortRule::LargestReal> sorting(m_ritz_val.data(), m_nev);
364 SortEigenvalue<Complex, SortRule::LargestImag> sorting(m_ritz_val.data(), m_nev);
370 SortEigenvalue<Complex, SortRule::SmallestMagn> sorting(m_ritz_val.data(), m_nev);
376 SortEigenvalue<Complex, SortRule::SmallestReal> sorting(m_ritz_val.data(), m_nev);
382 SortEigenvalue<Complex, SortRule::SmallestImag> sorting(m_ritz_val.data(), m_nev);
387 throw std::invalid_argument(
"unsupported sorting rule");
390 ComplexVector new_ritz_val(m_ncv);
391 ComplexMatrix new_ritz_vec(m_ncv, m_nev);
392 BoolArray new_ritz_conv(m_nev);
394 for (Index i = 0; i < m_nev; i++)
396 new_ritz_val[i] = m_ritz_val[ind[i]];
397 new_ritz_vec.col(i).noalias() = m_ritz_vec.col(ind[i]);
398 new_ritz_conv[i] = m_ritz_conv[ind[i]];
401 m_ritz_val.swap(new_ritz_val);
402 m_ritz_vec.swap(new_ritz_vec);
403 m_ritz_conv.swap(new_ritz_conv);
409 GenEigsBase(OpType& op,
const BOpType& Bop, Index nev, Index ncv) :
413 m_ncv(ncv > m_n ? m_n : ncv),
416 m_fac(ArnoldiOpType(op, Bop), m_ncv),
419 if (nev < 1 || nev > m_n - 2)
420 throw std::invalid_argument(
"nev must satisfy 1 <= nev <= n - 2, n is the size of matrix");
422 if (ncv < nev + 2 || ncv > m_n)
423 throw std::invalid_argument(
"ncv must satisfy nev + 2 <= ncv <= n, n is the size of matrix");
442 void init(
const Scalar* init_resid)
445 m_ritz_val.resize(m_ncv);
446 m_ritz_vec.resize(m_ncv, m_nev);
447 m_ritz_est.resize(m_ncv);
448 m_ritz_conv.resize(m_nev);
450 m_ritz_val.setZero();
451 m_ritz_vec.setZero();
452 m_ritz_est.setZero();
453 m_ritz_conv.setZero();
459 MapConstVec v0(init_resid, m_n);
460 m_fac.init(v0, m_nmatop);
442 void init(
const Scalar* init_resid) {
…}
472 SimpleRandom<Scalar> rng(0);
473 Vector init_resid = rng.random_vec(m_n);
474 init(init_resid.data());
505 m_fac.factorize_from(1, m_ncv, m_nmatop);
506 retrieve_ritzpair(selection);
508 Index i, nconv = 0, nev_adj;
509 for (i = 0; i < maxit; i++)
511 nconv = num_converged(tol);
515 nev_adj = nev_adjusted(nconv);
516 restart(nev_adj, selection);
519 sort_ritzpair(sorting);
524 return (std::min)(m_nev, nconv);
552 const Index nconv = m_ritz_conv.cast<Index>().sum();
553 ComplexVector res(nconv);
559 for (Index i = 0; i < m_nev; i++)
563 res[j] = m_ritz_val[i];
582 const Index nconv = m_ritz_conv.cast<Index>().sum();
583 nvec = (std::min)(nvec, nconv);
584 ComplexMatrix res(m_n, nvec);
589 ComplexMatrix ritz_vec_conv(m_ncv, nvec);
591 for (Index i = 0; i < m_nev && j < nvec; i++)
595 ritz_vec_conv.col(j).noalias() = m_ritz_vec.col(i);
600 res.noalias() = m_fac.matrix_V() * ritz_vec_conv;