40 Mmn_.MultiplyRightWithAuxMatrix(
ppm_.getPpm_phi());
41 const Eigen::VectorXd& weight =
ppm_.getPpm_weight();
42 const Eigen::VectorXd& omega =
ppm_.getPpm_freq();
44 for (
Index i = 0; i < weight.size(); ++i) {
45 mode_factors_(i) = (weight(i) < 1.e-9) ? 0.0 : 0.5 * weight(i) * omega(i);
52 const Eigen::ArrayXd w =
ppm_.getPpm_weight().array();
53 return "PPM modes with weight > 0: " + std::to_string((w > 0.0).count()) +
54 " of " + std::to_string(w.size()) +
55 " (> 1e-3: " + std::to_string((w > 1
e-3).count()) +
56 ", > 1e-2: " + std::to_string((w > 1
e-2).count()) +
")" +
57 ((
ppm_.InvalidModes() > 0)
58 ?
"; WARNING: " + std::to_string(
ppm_.InvalidModes()) +
59 " with negative squared frequency (|.| used)"
72 double* out, Term term)
const {
78 const Eigen::MatrixXd& M =
Mmn_[gw_level + qpmin_offset];
79 const auto e =
rpa_.getRPAInputEnergies().array();
80 const Eigen::VectorXd& weight =
ppm_.getPpm_weight();
81 const Eigen::VectorXd& omega =
ppm_.getPpm_freq();
82 for (
Index i_aux = 0; i_aux <
Mmn_.auxsize(); i_aux++) {
85 if (weight(i_aux) < 1.e-9) {
88 const double ppm_freq = omega(i_aux);
89 const double fac = 0.5 * weight(i_aux) * ppm_freq;
91 const auto m2 = M.col(i_aux).array().square();
92 for (
Index k = 0; k < nfreq; ++k) {
93 const auto t_occ = (freqs[k] + ppm_freq) -
e.head(lumo);
94 const auto t_virt = (freqs[k] - ppm_freq) -
e.tail(levelsum - lumo);
95 out[k] += fac * ((m2.head(lumo) * term(t_occ)).sum() +
96 (m2.tail(levelsum - lumo) * term(t_virt)).sum());
102 double frequency)
const {
104 const double eta2 =
opt_.eta *
opt_.eta;
107 [eta2](
const auto& t) {
return t / (t.square() + eta2); });
112 double frequency)
const {
113 const double eta2 =
opt_.eta *
opt_.eta;
114 double dsigma_domega = 0.0;
116 [eta2](
const auto& t) {
117 return (eta2 - t.square()) / (t.square() + eta2).square();
119 return dsigma_domega;
123 Index gw_level,
const Eigen::VectorXd& frequencies)
const {
124 const Index nfreq = frequencies.size();
125 for (
Index i = 0; i < nfreq; ++i) {
142 double frequency2)
const {
146 const double eta2 =
opt_.eta *
opt_.eta;
149 const Eigen::VectorXd ppm_weight =
ppm_.getPpm_weight();
150 const Eigen::VectorXd ppm_freqs =
ppm_.getPpm_freq();
152 const Eigen::VectorXd RPAEnergies =
rpa_.getRPAInputEnergies();
154 for (
Index i_aux = 0; i_aux < auxsize; i_aux++) {
157 if (ppm_weight(i_aux) < 1.e-9) {
160 const double ppm_freq = ppm_freqs(i_aux);
161 const double fac = 0.25 * ppm_weight(i_aux) * ppm_freq;
162 const Eigen::MatrixXd& Mmn1 =
Mmn_[gw_level1 + qpmin_offset];
163 const Eigen::MatrixXd& Mmn2 =
Mmn_[gw_level2 + qpmin_offset];
164 const Eigen::ArrayXd Mmn1xMmn2 =
165 Mmn1.col(i_aux).cwiseProduct(Mmn2.col(i_aux));
166 Eigen::ArrayXd temp1 = RPAEnergies;
167 temp1.segment(0, lumo) -= ppm_freq;
168 temp1.segment(lumo, levelsum - lumo) += ppm_freq;
169 Eigen::ArrayXd temp2 = (frequency2 - temp1);
170 temp1 = (frequency1 - temp1);
172 fac * ((temp1 / (temp1.abs2() + eta2) + temp2 / (temp2.abs2() + eta2)) *
180 const Eigen::VectorXd& frequencies)
const {
184 const double eta2 =
opt_.eta *
opt_.eta;
188 const Eigen::VectorXd& ppm_weight =
ppm_.getPpm_weight();
189 const Eigen::VectorXd& ppm_freqs =
ppm_.getPpm_freq();
190 const Eigen::ArrayXd energies =
rpa_.getRPAInputEnergies().array();
194 const Eigen::MatrixXd A =
196 const Eigen::MatrixXd& M =
Mmn_[m + qpmin_offset];
197 X.resize(levelsum, auxsize);
198 const double w = frequencies(m);
199 Eigen::ArrayXd t(levelsum);
200 for (
Index i_aux = 0; i_aux < auxsize; ++i_aux) {
201 if (ppm_weight(i_aux) < 1.e-9) {
202 X.col(i_aux).setZero();
205 const double ppm_freq = ppm_freqs(i_aux);
206 const double fac = 0.25 * ppm_weight(i_aux) * ppm_freq;
208 t.head(lumo) += ppm_freq;
209 t.tail(levelsum - lumo) -= ppm_freq;
211 (fac * M.col(i_aux).array() * t / (t.abs2() + eta2)).matrix();
214 Eigen::MatrixXd result = A + A.transpose();
215 result.diagonal().setZero();
double CalcCorrelationOffDiagElement(Index gw_level1, Index gw_level2, double frequency1, double frequency2) const final
void AccumulateDiag(Index gw_level, const double *freqs, Index nfreq, double *out, Term term) const
Eigen::VectorXd CalcCorrelationDiagElements(Index gw_level, const Eigen::VectorXd &frequencies) const final
double CalcCorrelationDiagElement(Index gw_level, double frequency) const final
Eigen::VectorXd mode_factors_
void PrepareScreening() final
double CalcCorrelationDiagElementDerivative(Index gw_level, double frequency) const final
Eigen::MatrixXd CalcCorrelationOffDiag(const Eigen::VectorXd &frequencies) const final
std::string ScreeningSummary() const final
One line about the screening just prepared (empty if nothing to say).
Eigen::MatrixXd PairContraction(Index nrows, const std::function< void(Index, Eigen::MatrixXd &)> &makeX) const
void CountDiagEval() const
Eigen::VectorXd Values(const ExactPoles &poles, const double *residues, const Eigen::VectorXd &w)
Charge transport classes.
Provides a means for comparing floating point numbers.
Pole sums of the exact (RPA spectral) correlation self-energy.