7 #ifndef SPECTRA_SYM_EIGS_BASE_H
8 #define SPECTRA_SYM_EIGS_BASE_H
17 #include "Util/Version.h"
18 #include "Util/TypeTraits.h"
19 #include "Util/SelectionRule.h"
20 #include "Util/CompInfo.h"
21 #include "Util/SimpleRandom.h"
22 #include "MatOp/internal/ArnoldiOp.h"
23 #include "LinAlg/UpperHessenbergQR.h"
24 #include "LinAlg/TridiagEigen.h"
25 #include "LinAlg/Lanczos.h"
42 template <
typename OpType,
typename BOpType>
46 using Scalar =
typename OpType::Scalar;
47 using Index = Eigen::Index;
48 using Matrix = Eigen::Matrix<Scalar, Eigen::Dynamic, Eigen::Dynamic>;
49 using Vector = Eigen::Matrix<Scalar, Eigen::Dynamic, 1>;
50 using Array = Eigen::Array<Scalar, Eigen::Dynamic, 1>;
51 using BoolArray = Eigen::Array<bool, Eigen::Dynamic, 1>;
52 using MapMat = Eigen::Map<Matrix>;
53 using MapVec = Eigen::Map<Vector>;
54 using MapConstVec = Eigen::Map<const Vector>;
56 using ArnoldiOpType = ArnoldiOp<Scalar, OpType, BOpType>;
57 using LanczosFac = Lanczos<Scalar, ArnoldiOpType>;
68 std::vector<OpType> m_op_container;
82 BoolArray m_ritz_conv;
87 static std::vector<OpType> create_op_container(OpType&& rval)
89 std::vector<OpType> container;
90 container.emplace_back(std::move(rval));
95 void restart(Index k,
SortRule selection)
102 TridiagQR<Scalar> decomp(m_ncv);
103 Matrix Q = Matrix::Identity(m_ncv, m_ncv);
106 const int nshift = m_ncv - k;
107 Vector shifts = m_ritz_val.tail(nshift);
108 std::sort(shifts.data(), shifts.data() + nshift, [](
const Scalar& v1,
const Scalar& v2) { return abs(v1) > abs(v2); });
110 for (Index i = 0; i < nshift; i++)
113 decomp.compute(m_fac.matrix_H(), shifts[i]);
120 m_fac.compress_H(decomp);
124 m_fac.factorize_from(k, m_ncv, m_nmatop);
126 retrieve_ritzpair(selection);
130 Index num_converged(
const Scalar& tol)
135 constexpr Scalar eps = TypeTraits<Scalar>::epsilon();
138 const Scalar eps23 = pow(eps, Scalar(2) / 3);
141 Array thresh = tol * m_ritz_val.head(m_nev).array().abs().max(eps23);
142 Array resid = m_ritz_est.head(m_nev).array().abs() * m_fac.f_norm();
144 m_ritz_conv = (resid < thresh);
154 return m_ritz_conv.count();
158 Index nev_adjusted(Index nconv)
164 constexpr Scalar near_0 = TypeTraits<Scalar>::min() * Scalar(10);
166 Index nev_new = m_nev;
167 for (Index i = m_nev; i < m_ncv; i++)
168 if (abs(m_ritz_est[i]) < near_0)
172 nev_new += (std::min)(nconv, (m_ncv - nev_new) / 2);
173 if (nev_new == 1 && m_ncv >= 6)
175 else if (nev_new == 1 && m_ncv > 2)
178 if (nev_new > m_ncv - 1)
185 void retrieve_ritzpair(
SortRule selection)
187 TridiagEigen<Scalar> decomp(m_fac.matrix_H());
188 const Vector& evals = decomp.eigenvalues();
189 const Matrix& evecs = decomp.eigenvectors();
199 std::vector<Index> ind = argsort(selection, evals, m_ncv);
202 for (Index i = 0; i < m_ncv; i++)
204 m_ritz_val[i] = evals[ind[i]];
205 m_ritz_est[i] = evecs(m_ncv - 1, ind[i]);
207 for (Index i = 0; i < m_nev; i++)
209 m_ritz_vec.col(i).noalias() = evecs.col(ind[i]);
216 virtual void sort_ritzpair(
SortRule sort_rule)
220 throw std::invalid_argument(
"unsupported sorting rule");
222 std::vector<Index> ind = argsort(sort_rule, m_ritz_val, m_nev);
224 Vector new_ritz_val(m_ncv);
225 Matrix new_ritz_vec(m_ncv, m_nev);
226 BoolArray new_ritz_conv(m_nev);
228 for (Index i = 0; i < m_nev; i++)
230 new_ritz_val[i] = m_ritz_val[ind[i]];
231 new_ritz_vec.col(i).noalias() = m_ritz_vec.col(ind[i]);
232 new_ritz_conv[i] = m_ritz_conv[ind[i]];
235 m_ritz_val.swap(new_ritz_val);
236 m_ritz_vec.swap(new_ritz_vec);
237 m_ritz_conv.swap(new_ritz_conv);
244 SymEigsBase(OpType& op,
const BOpType& Bop, Index nev, Index ncv) :
248 m_ncv(ncv > m_n ? m_n : ncv),
251 m_fac(ArnoldiOpType(op, Bop), m_ncv),
254 if (nev < 1 || nev > m_n - 1)
255 throw std::invalid_argument(
"nev must satisfy 1 <= nev <= n - 1, n is the size of matrix");
257 if (ncv <= nev || ncv > m_n)
258 throw std::invalid_argument(
"ncv must satisfy nev < ncv <= n, n is the size of matrix");
262 SymEigsBase(OpType&& op,
const BOpType& Bop, Index nev, Index ncv) :
263 m_op_container(create_op_container(std::move(op))),
264 m_op(m_op_container.front()),
267 m_ncv(ncv > m_n ? m_n : ncv),
270 m_fac(ArnoldiOpType(m_op, Bop), m_ncv),
273 if (nev < 1 || nev > m_n - 1)
274 throw std::invalid_argument(
"nev must satisfy 1 <= nev <= n - 1, n is the size of matrix");
276 if (ncv <= nev || ncv > m_n)
277 throw std::invalid_argument(
"ncv must satisfy nev < ncv <= n, n is the size of matrix");
296 void init(
const Scalar* init_resid)
299 m_ritz_val.resize(m_ncv);
300 m_ritz_vec.resize(m_ncv, m_nev);
301 m_ritz_est.resize(m_ncv);
302 m_ritz_conv.resize(m_nev);
304 m_ritz_val.setZero();
305 m_ritz_vec.setZero();
306 m_ritz_est.setZero();
307 m_ritz_conv.setZero();
313 MapConstVec v0(init_resid, m_n);
314 m_fac.init(v0, m_nmatop);
326 SimpleRandom<Scalar> rng(0);
327 Vector init_resid = rng.random_vec(m_n);
328 init(init_resid.data());
330 std::cout <<
"init_vec = " << init_resid.head(5).transpose() << std::endl
360 m_fac.factorize_from(1, m_ncv, m_nmatop);
361 retrieve_ritzpair(selection);
363 Index i, nconv = 0, nev_adj;
364 for (i = 0; i < maxit; i++)
366 nconv = num_converged(tol);
370 nev_adj = nev_adjusted(nconv);
371 restart(nev_adj, selection);
374 sort_ritzpair(sorting);
379 return (std::min)(m_nev, nconv);
407 const Index nconv = m_ritz_conv.count();
414 for (Index i = 0; i < m_nev; i++)
418 res[j] = m_ritz_val[i];
437 const Index nconv = m_ritz_conv.count();
438 nvec = (std::min)(nvec, nconv);
439 Matrix res(m_n, nvec);
444 Matrix ritz_vec_conv(m_ncv, nvec);
446 for (Index i = 0; i < m_nev && j < nvec; i++)
450 ritz_vec_conv.col(j).noalias() = m_ritz_vec.col(i);
455 res.noalias() = m_fac.matrix_V() * ritz_vec_conv;
Index num_operations() const
Index num_iterations() const
void init(const Scalar *init_resid)
virtual Matrix eigenvectors(Index nvec) const
Index compute(SortRule selection=SortRule::LargestMagn, Index maxit=1000, Scalar tol=1e-10, SortRule sorting=SortRule::LargestAlge)
Vector eigenvalues() const
virtual Matrix eigenvectors() const
@ SmallestAlge
Select eigenvalues with smallest algebraic value. Only for symmetric eigen solvers.
@ Successful
Computation was successful.