7 #ifndef SPECTRA_GEN_EIGS_COMPLEX_SHIFT_SOLVER_H
8 #define SPECTRA_GEN_EIGS_COMPLEX_SHIFT_SOLVER_H
12 #include "GenEigsBase.h"
13 #include "Util/SelectionRule.h"
14 #include "MatOp/DenseGenComplexShiftSolve.h"
32 template <
typename OpType = DenseGenComplexShiftSolve<
double>>
36 using Scalar =
typename OpType::Scalar;
37 using Index = Eigen::Index;
38 using Complex = std::complex<Scalar>;
39 using Vector = Eigen::Matrix<Scalar, Eigen::Dynamic, 1>;
40 using ComplexArray = Eigen::Array<Complex, Eigen::Dynamic, 1>;
47 using Base::m_ritz_val;
48 using Base::m_ritz_vec;
50 const Scalar m_sigmar;
51 const Scalar m_sigmai;
54 void sort_ritzpair(
SortRule sort_rule)
override
79 SimpleRandom<Scalar> rng(0);
80 const Scalar shiftr = rng.random() * m_sigmar + rng.random();
81 const Complex shift = Complex(shiftr, Scalar(0));
82 m_op.set_shift(shiftr, Scalar(0));
85 Vector v_real(m_n), v_imag(m_n), OPv_real(m_n), OPv_imag(m_n);
86 constexpr Scalar eps = TypeTraits<Scalar>::epsilon();
87 for (Index i = 0; i < m_nev; i++)
89 v_real.noalias() = m_fac.matrix_V() * m_ritz_vec.col(i).real();
90 v_imag.noalias() = m_fac.matrix_V() * m_ritz_vec.col(i).imag();
91 m_op.perform_op(v_real.data(), OPv_real.data());
92 m_op.perform_op(v_imag.data(), OPv_imag.data());
95 const Complex nu = m_ritz_val[i];
96 const Complex root_part1 = m_sigmar + Scalar(0.5) / nu;
97 const Complex root_part2 = Scalar(0.5) * sqrt(Scalar(1) - Scalar(4) * m_sigmai * m_sigmai * (nu * nu)) / nu;
98 const Complex root1 = root_part1 + root_part2;
99 const Complex root2 = root_part1 - root_part2;
102 Scalar err1 = Scalar(0), err2 = Scalar(0);
103 for (
int k = 0; k < m_n; k++)
105 const Complex rhs1 = Complex(v_real[k], v_imag[k]) / (root1 - shift);
106 const Complex rhs2 = Complex(v_real[k], v_imag[k]) / (root2 - shift);
107 const Complex OPv = Complex(OPv_real[k], OPv_imag[k]);
108 err1 += norm(OPv - rhs1);
109 err2 += norm(OPv - rhs2);
112 const Complex lambdaj = (err1 < err2) ? root1 : root2;
113 m_ritz_val[i] = lambdaj;
115 if (abs(Eigen::numext::imag(lambdaj)) > eps)
117 m_ritz_val[i + 1] = Eigen::numext::conj(lambdaj);
122 m_ritz_val[i] = Complex(Eigen::numext::real(lambdaj), Scalar(0));
126 Base::sort_ritzpair(sort_rule);
150 Base(op, IdentityBOp(), nev, ncv),
151 m_sigmar(sigmar), m_sigmai(sigmai)
153 op.set_shift(m_sigmar, m_sigmai);
GenEigsComplexShiftSolver(OpType &op, Index nev, Index ncv, const Scalar &sigmar, const Scalar &sigmai)