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);
99 Eigen::MatrixXd Mmn_RPA;
103 const Index qp_end_occ =
105 if (m_level >= qp_offset_m && m_level < qp_end_occ) {
107 const Index v_qp = m_level - qp_offset_m;
108 Mmn_RPA = Eigen::MatrixXd::Zero(n_unocc,
Mmn_.auxsize());
109 for (
Index vp = 0; vp < qptotal; vp++) {
110 Mmn_RPA.noalias() += (*qsgw_U_)(vp, v_qp) *
111 Mmn_[vp + qp_offset_m].bottomRows(n_unocc);
114 Mmn_RPA =
Mmn_[m_level].bottomRows(n_unocc);
117 Mmn_RPA =
Mmn_[m_level].bottomRows(n_unocc);
121 const Eigen::ArrayXd deltaE =
122 energies_.tail(n_unocc).array() - qp_energy_m;
123 Eigen::VectorXd denom;
125 denom = 4 * deltaE / (deltaE.square() + freq2);
127 Eigen::ArrayXd deltEf = deltaE - frequency;
128 Eigen::ArrayXd sum = deltEf / (deltEf.square() + eta2);
129 deltEf = deltaE + frequency;
130 sum += deltEf / (deltEf.square() + eta2);
134 transform.
A_TDA(denom, threadid);
138 result.diagonal().array() += 1.0;
157#pragma omp for schedule(dynamic)
158 for (
Index m_level = 0; m_level < n_occ; m_level++) {
160 const double qp_energy_m =
energies_(m_level);
163 Eigen::MatrixXd Mmn_RPA;
167 const Index qp_end_occ =
169 if (m_level >= qp_offset_m && m_level < qp_end_occ) {
170 const Index v_qp = m_level - qp_offset_m;
171 Mmn_RPA = Eigen::MatrixXd::Zero(n_unocc,
Mmn_.auxsize());
172 for (
Index vp = 0; vp < qptotal; vp++) {
173 Mmn_RPA.noalias() += (*qsgw_U_)(vp, v_qp) *
174 Mmn_[vp + qp_offset_m].bottomRows(n_unocc);
177 Mmn_RPA =
Mmn_[m_level].bottomRows(n_unocc);
180 Mmn_RPA =
Mmn_[m_level].bottomRows(n_unocc);
184 const Eigen::ArrayXd deltaE =
185 energies_.tail(n_unocc).array() - qp_energy_m;
187 Eigen::ArrayXd deltaEm = frequency.real() - deltaE;
188 Eigen::ArrayXd deltaEp = frequency.real() + deltaE;
190 double sigma_1 = std::pow(frequency.imag() +
eta_, 2);
191 double sigma_2 = std::pow(frequency.imag() -
eta_, 2);
193 Eigen::VectorXd chi =
194 deltaEm * (deltaEm.cwiseAbs2() + sigma_1).cwiseInverse() -
195 deltaEp * (deltaEp.cwiseAbs2() + sigma_2).cwiseInverse();
196 transform.
A_TDA(chi, threadid);
200 result.diagonal().array() += 1.0;
208 const Index rpasize = n_occ * n_unocc;
217 Eigen::MatrixXd& C = ApB;
218 C.applyOnTheLeft(AmB.cwiseSqrt().asDiagonal());
219 C.applyOnTheRight(AmB.cwiseSqrt().asDiagonal());
224 sol.
omega = Eigen::VectorXd::Zero(es.eigenvalues().size());
225 sol.
omega = es.eigenvalues().cwiseSqrt();
229 std::ostringstream oss;
230 oss <<
TimeStamp() <<
" RKS H2p poles (first 20, eV): ";
231 const Index nprint = std::min<Index>(20, sol.
omega.size());
232 for (
Index i = 0; i < nprint; ++i) {
233 oss << std::fixed << std::setprecision(6)
235 if (i + 1 < nprint) {
243 <<
" Lowest neutral excitation energy (eV): "
254 sol.
XpY = Eigen::MatrixXd(rpasize, rpasize);
256 Eigen::VectorXd AmB_sqrt = AmB.cwiseSqrt();
257 Eigen::VectorXd Omega_sqrt_inv = sol.
omega.cwiseSqrt().cwiseInverse();
258 for (
int s = 0; s < rpasize; s++) {
260 Omega_sqrt_inv(s) * AmB_sqrt.cwiseProduct(es.eigenvectors().col(s));
270 const Index rpasize = n_occ * n_unocc;
272 Eigen::VectorXd AmB = Eigen::VectorXd::Zero(rpasize);
273 for (
Index v = 0; v < n_occ; v++) {
275 AmB.segment(i, n_unocc) =
285 const Index rpasize = n_occ * n_unocc;
287 Eigen::MatrixXd ApB = Eigen::MatrixXd::Zero(rpasize, rpasize);
290 const Index qp_offset_m_apb =
293 const Index qp_end_occ_apb =
299 std::vector<Eigen::MatrixXd> Mmn_virt_rotated(n_occ);
300 for (
Index v = 0; v < n_occ; v++) {
301 if (
qsgw_U_ !=
nullptr && v >= qp_offset_m_apb && v < qp_end_occ_apb) {
302 const Index v_qp = v - qp_offset_m_apb;
303 Mmn_virt_rotated[v] = Eigen::MatrixXd::Zero(n_unocc,
Mmn_.auxsize());
304 for (
Index vp = 0; vp < qptotal_apb; vp++) {
305 Mmn_virt_rotated[v].noalias() +=
306 (*qsgw_U_)(vp, v_qp) *
307 Mmn_[vp + qp_offset_m_apb].middleRows(n_occ, n_unocc);
310 Mmn_virt_rotated[v] =
Mmn_[v].middleRows(n_occ, n_unocc);
313#pragma omp parallel for schedule(guided)
314 for (
Index v2 = 0; v2 < n_occ; v2++) {
316 const Eigen::MatrixXd Mmn_v2T = Mmn_virt_rotated[v2].transpose();
317 for (
Index v1 = v2; v1 < n_occ; v1++) {
320 ApB.block(i1, i2, n_unocc, n_unocc) =
321 2 * 2 * Mmn_virt_rotated[v1] * Mmn_v2T;
329 const Eigen::MatrixXd& C)
const {
331 <<
TimeStamp() <<
" Diagonalizing two-particle Hamiltonian "
333 Eigen::SelfAdjointEigenSolver<Eigen::MatrixXd> es(C);
335 <<
TimeStamp() <<
" Diagonalization done " << std::flush;
336 double minCoeff = es.eigenvalues().minCoeff();
337 if (minCoeff <= 0.0) {
339 <<
TimeStamp() <<
" Detected non-positive eigenvalue: " << minCoeff
341 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)
const Eigen::MatrixXd * qsgw_U_
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.