33 const Eigen::VectorXd& gwaenergies,
54 Index qpmax = qpmin + gwsize - 1;
61 energies_.head(qpmin).array() -= max_correction_occ;
68 Index range = max - min + 1;
69 Eigen::VectorXd corrections =
72 return (corrections.cwiseAbs()).maxCoeff();
82 const double freq2 = frequency * frequency;
91#pragma omp for schedule(dynamic)
92 for (
Index m_level = 0; m_level < n_occ; m_level++) {
93 const double qp_energy_m =
energies_(m_level);
95 Eigen::MatrixXd Mmn_RPA =
Mmn_[m_level].bottomRows(n_unocc);
97 const Eigen::ArrayXd deltaE =
98 energies_.tail(n_unocc).array() - qp_energy_m;
99 Eigen::VectorXd denom;
101 denom = 4 * deltaE / (deltaE.square() + freq2);
103 Eigen::ArrayXd deltEf = deltaE - frequency;
104 Eigen::ArrayXd sum = deltEf / (deltEf.square() + eta2);
105 deltEf = deltaE + frequency;
106 sum += deltEf / (deltEf.square() + eta2);
110 transform.
A_TDA(denom, threadid);
114 result.diagonal().array() += 1.0;
133#pragma omp for schedule(dynamic)
134 for (
Index m_level = 0; m_level < n_occ; m_level++) {
136 const double qp_energy_m =
energies_(m_level);
137 Eigen::MatrixXd Mmn_RPA =
Mmn_[m_level].bottomRows(n_unocc);
139 const Eigen::ArrayXd deltaE =
140 energies_.tail(n_unocc).array() - qp_energy_m;
142 Eigen::ArrayXd deltaEm = frequency.real() - deltaE;
143 Eigen::ArrayXd deltaEp = frequency.real() + deltaE;
145 double sigma_1 = std::pow(frequency.imag() +
eta_, 2);
146 double sigma_2 = std::pow(frequency.imag() -
eta_, 2);
148 Eigen::VectorXd chi =
149 deltaEm * (deltaEm.cwiseAbs2() + sigma_1).cwiseInverse() -
150 deltaEp * (deltaEp.cwiseAbs2() + sigma_2).cwiseInverse();
151 transform.
A_TDA(chi, threadid);
155 result.diagonal().array() += 1.0;
163 const Index rpasize = n_occ * n_unocc;
172 Eigen::MatrixXd& C = ApB;
173 C.applyOnTheLeft(AmB.cwiseSqrt().asDiagonal());
174 C.applyOnTheRight(AmB.cwiseSqrt().asDiagonal());
179 sol.
omega = Eigen::VectorXd::Zero(es.eigenvalues().size());
180 sol.
omega = es.eigenvalues().cwiseSqrt();
184 std::ostringstream oss;
185 oss <<
TimeStamp() <<
" RKS H2p poles (first 20, eV): ";
186 const Index nprint = std::min<Index>(20, sol.
omega.size());
187 for (
Index i = 0; i < nprint; ++i) {
188 oss << std::fixed << std::setprecision(6)
190 if (i + 1 < nprint) {
198 <<
" Lowest neutral excitation energy (eV): "
209 sol.
XpY = Eigen::MatrixXd(rpasize, rpasize);
211 Eigen::VectorXd AmB_sqrt = AmB.cwiseSqrt();
212 Eigen::VectorXd Omega_sqrt_inv = sol.
omega.cwiseSqrt().cwiseInverse();
213 for (
int s = 0; s < rpasize; s++) {
215 Omega_sqrt_inv(s) * AmB_sqrt.cwiseProduct(es.eigenvectors().col(s));
225 const Index rpasize = n_occ * n_unocc;
227 Eigen::VectorXd AmB = Eigen::VectorXd::Zero(rpasize);
228 for (
Index v = 0; v < n_occ; v++) {
230 AmB.segment(i, n_unocc) =
240 const Index rpasize = n_occ * n_unocc;
242 Eigen::MatrixXd ApB = Eigen::MatrixXd::Zero(rpasize, rpasize);
243#pragma omp parallel for schedule(guided)
244 for (
Index v2 = 0; v2 < n_occ; v2++) {
246 const Eigen::MatrixXd Mmn_v2T =
247 Mmn_[v2].middleRows(n_occ, n_unocc).transpose();
248 for (
Index v1 = v2; v1 < n_occ; v1++) {
251 ApB.block(i1, i2, n_unocc, n_unocc) =
252 2 * 2 *
Mmn_[v1].middleRows(n_occ, n_unocc) * Mmn_v2T;
260 const Eigen::MatrixXd& C)
const {
262 <<
TimeStamp() <<
" Diagonalizing two-particle Hamiltonian "
264 Eigen::SelfAdjointEigenSolver<Eigen::MatrixXd> es(C);
266 <<
TimeStamp() <<
" Diagonalization done " << std::flush;
267 double minCoeff = es.eigenvalues().minCoeff();
268 if (minCoeff <= 0.0) {
270 <<
TimeStamp() <<
" Detected non-positive eigenvalue: " << minCoeff
272 throw std::runtime_error(
"Detected non-positive eigenvalue.");
void A_TDA(const Eigen::VectorXd &vec, Index OpenmpThread)
Eigen::MatrixXd getReductionVar()
void createTemporaries(Index rows, Index cols)
void PushMatrix(const Eigen::MatrixXd &mat, Index OpenmpThread)
Eigen::MatrixXd Calculate_H2p_ApB() const
void ShiftUncorrectedEnergies(const Eigen::VectorXd &dftenergies, Index qpmin, Index gwsize)
Eigen::VectorXd energies_
Eigen::MatrixXd calculate_epsilon(double frequency) const
Eigen::MatrixXd calculate_epsilon_r(double frequency) const
const TCMatrix_gwbse & Mmn_
Eigen::VectorXd Calculate_H2p_AmB() const
Eigen::SelfAdjointEigenSolver< Eigen::MatrixXd > Diagonalize_H2p_C(const Eigen::MatrixXd &C) const
rpa_eigensolution Diagonalize_H2p() const
void UpdateRPAInputEnergies(const Eigen::VectorXd &dftenergies, const Eigen::VectorXd &gwaenergies, Index qpmin)
double getMaxCorrection(const Eigen::VectorXd &dftenergies, Index min, Index max) const
Timestamp returns the current time as a string Example: cout << TimeStamp()
This class transforms a pair of indices v,c into a compound index I, via I=ctotal*v+c the fast dimens...
Index I(Index v, Index c) const
#define XTP_LOG(level, log)
Charge transport classes.
Provides a means for comparing floating point numbers.