49 using Scalar =
typename OpType::Scalar;
54 using RealScalar =
typename Eigen::NumTraits<Scalar>::Real;
55 using Index = Eigen::Index;
56 using Matrix = Eigen::Matrix<Scalar, Eigen::Dynamic, Eigen::Dynamic>;
57 using Vector = Eigen::Matrix<Scalar, Eigen::Dynamic, 1>;
58 using RealMatrix = Eigen::Matrix<RealScalar, Eigen::Dynamic, Eigen::Dynamic>;
59 using RealVector = Eigen::Matrix<RealScalar, Eigen::Dynamic, 1>;
60 using RealArray = Eigen::Array<RealScalar, Eigen::Dynamic, 1>;
61 using BoolArray = Eigen::Array<bool, Eigen::Dynamic, 1>;
62 using MapMat = Eigen::Map<Matrix>;
63 using MapVec = Eigen::Map<Vector>;
64 using MapConstVec = Eigen::Map<const Vector>;
66 using ArnoldiOpType = ArnoldiOp<OpType, BOpType>;
67 using LanczosFac = Lanczos<ArnoldiOpType>;
78 std::vector<OpType> m_op_container;
87 RealVector m_ritz_val;
90 RealMatrix m_ritz_vec;
91 RealVector m_ritz_est;
92 BoolArray m_ritz_conv;
97 static std::vector<OpType> create_op_container(OpType&& rval)
99 std::vector<OpType> container;
100 container.emplace_back(std::move(rval));
105 void restart(Index k,
SortRule selection)
113 TridiagQR<RealScalar> decomp(m_ncv);
115 RealMatrix Q = RealMatrix::Identity(m_ncv, m_ncv);
118 const int nshift = m_ncv - k;
119 RealVector shifts = m_ritz_val.tail(nshift);
120 std::sort(shifts.data(), shifts.data() + nshift,
121 [](
const RealScalar& v1,
const RealScalar& v2) { return abs(v1) > abs(v2); });
124 for (Index i = 0; i < nshift; i++)
128 decomp.compute(m_fac.matrix_H().real(), shifts[i]);
135 m_fac.compress_H(decomp);
152 m_fac.factorize_from(k, m_ncv, m_nmatop);
154 retrieve_ritzpair(selection);
158 Index num_converged(
const RealScalar& tol)
163 const RealScalar eps = TypeTraits<RealScalar>::epsilon();
166 const RealScalar eps23 = pow(eps, RealScalar(2) / 3);
169 RealArray thresh = tol * m_ritz_val.head(m_nev).array().abs().max(eps23);
170 RealArray resid = m_ritz_est.head(m_nev).array().abs() * m_fac.f_norm();
172 m_ritz_conv = (resid < thresh);
174 return m_ritz_conv.count();
178 Index nev_adjusted(Index nconv)
184 const RealScalar near_0 = TypeTraits<RealScalar>::min() * RealScalar(10);
186 Index nev_new = m_nev;
187 for (Index i = m_nev; i < m_ncv; i++)
188 if (abs(m_ritz_est[i]) < near_0)
192 nev_new += (std::min)(nconv, (m_ncv - nev_new) / 2);
193 if (nev_new == 1 && m_ncv >= 6)
195 else if (nev_new == 1 && m_ncv > 2)
198 if (nev_new > m_ncv - 1)
205 void retrieve_ritzpair(
SortRule selection)
207 TridiagEigen<RealScalar> decomp(m_fac.matrix_H().real());
208 const RealVector& evals = decomp.eigenvalues();
209 const RealMatrix& evecs = decomp.eigenvectors();
212 std::vector<Index> ind = argsort(selection, evals, m_ncv);
215 for (Index i = 0; i < m_ncv; i++)
217 m_ritz_val[i] = evals[ind[i]];
218 m_ritz_est[i] = evecs(m_ncv - 1, ind[i]);
220 for (Index i = 0; i < m_nev; i++)
222 m_ritz_vec.col(i).noalias() = evecs.col(ind[i]);
229 virtual void sort_ritzpair(
SortRule sort_rule)
233 throw std::invalid_argument(
"unsupported sorting rule");
235 std::vector<Index> ind = argsort(sort_rule, m_ritz_val, m_nev);
237 RealVector new_ritz_val(m_ncv);
238 RealMatrix new_ritz_vec(m_ncv, m_nev);
239 BoolArray new_ritz_conv(m_nev);
241 for (Index i = 0; i < m_nev; i++)
243 new_ritz_val[i] = m_ritz_val[ind[i]];
244 new_ritz_vec.col(i).noalias() = m_ritz_vec.col(ind[i]);
245 new_ritz_conv[i] = m_ritz_conv[ind[i]];
248 m_ritz_val.swap(new_ritz_val);
249 m_ritz_vec.swap(new_ritz_vec);
250 m_ritz_conv.swap(new_ritz_conv);
257 HermEigsBase(OpType& op,
const BOpType& Bop, Index nev, Index ncv) :
261 m_ncv(ncv > m_n ? m_n : ncv),
264 m_fac(ArnoldiOpType(op, Bop), m_ncv),
267 if (nev < 1 || nev > m_n - 1)
268 throw std::invalid_argument(
"nev must satisfy 1 <= nev <= n - 1, n is the size of matrix");
270 if (ncv <= nev || ncv > m_n)
271 throw std::invalid_argument(
"ncv must satisfy nev < ncv <= n, n is the size of matrix");
275 HermEigsBase(OpType&& op,
const BOpType& Bop, Index nev, Index ncv) :
276 m_op_container(create_op_container(std::move(op))),
277 m_op(m_op_container.front()),
280 m_ncv(ncv > m_n ? m_n : ncv),
283 m_fac(ArnoldiOpType(m_op, Bop), m_ncv),
286 if (nev < 1 || nev > m_n - 1)
287 throw std::invalid_argument(
"nev must satisfy 1 <= nev <= n - 1, n is the size of matrix");
289 if (ncv <= nev || ncv > m_n)
290 throw std::invalid_argument(
"ncv must satisfy nev < ncv <= n, n is the size of matrix");
309 void init(
const Scalar* init_resid)
312 m_ritz_val.resize(m_ncv);
313 m_ritz_vec.resize(m_ncv, m_nev);
314 m_ritz_est.resize(m_ncv);
315 m_ritz_conv.resize(m_nev);
317 m_ritz_val.setZero();
318 m_ritz_vec.setZero();
319 m_ritz_est.setZero();
320 m_ritz_conv.setZero();
326 MapConstVec v0(init_resid, m_n);
327 m_fac.init(v0, m_nmatop);
309 void init(
const Scalar* init_resid) {
…}
339 SimpleRandom<Scalar> rng(0);
340 Vector init_resid = rng.random_vec(m_n);
341 init(init_resid.data());
370 m_fac.factorize_from(1, m_ncv, m_nmatop);
371 retrieve_ritzpair(selection);
373 Index i, nconv = 0, nev_adj;
374 for (i = 0; i < maxit; i++)
376 nconv = num_converged(tol);
380 nev_adj = nev_adjusted(nconv);
381 restart(nev_adj, selection);
384 sort_ritzpair(sorting);
389 return (std::min)(m_nev, nconv);
419 const Index nconv = m_ritz_conv.count();
420 RealVector res(nconv);
426 for (Index i = 0; i < m_nev; i++)
430 res[j] = m_ritz_val[i];
449 const Index nconv = m_ritz_conv.count();
450 nvec = (std::min)(nvec, nconv);
451 Matrix res(m_n, nvec);
456 RealMatrix ritz_vec_conv(m_ncv, nvec);
458 for (Index i = 0; i < m_nev && j < nvec; i++)
462 ritz_vec_conv.col(j).noalias() = m_ritz_vec.col(i);
467 res.noalias() = m_fac.matrix_V() * ritz_vec_conv;