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);
61 const Eigen::VectorXd& nu)
const {
65 const Eigen::VectorXd& w =
ppm_.getPpm_weight();
70 const Index n = w.size();
73 for (
Index i = 0; i < n; ++i) {
74 const double W = data.
omegas(i);
78 for (
Index j = 0; j < nu.size(); ++j) {
88 const Eigen::ArrayXd w =
ppm_.getPpm_weight().array();
89 return "PPM modes with weight > 0: " + std::to_string((w > 0.0).count()) +
90 " of " + std::to_string(w.size()) +
91 " (> 1e-3: " + std::to_string((w > 1
e-3).count()) +
92 ", > 1e-2: " + std::to_string((w > 1
e-2).count()) +
")" +
93 ((
ppm_.InvalidModes() > 0)
94 ?
"; WARNING: " + std::to_string(
ppm_.InvalidModes()) +
95 " with negative squared frequency (|.| used)"
108 double* out, Term term)
const {
114 const Eigen::MatrixXd& M =
Mmn_[gw_level + qpmin_offset];
115 const auto e =
rpa_.getRPAInputEnergies().array();
116 const Eigen::VectorXd& weight =
ppm_.getPpm_weight();
117 const Eigen::VectorXd& omega =
ppm_.getPpm_freq();
118 for (
Index i_aux = 0; i_aux <
Mmn_.auxsize(); i_aux++) {
121 if (weight(i_aux) < 1.e-9) {
124 const double ppm_freq = omega(i_aux);
125 const double fac = 0.5 * weight(i_aux) * ppm_freq;
127 const auto m2 = M.col(i_aux).array().square();
128 for (
Index k = 0; k < nfreq; ++k) {
129 const auto t_occ = (freqs[k] + ppm_freq) -
e.head(lumo);
130 const auto t_virt = (freqs[k] - ppm_freq) -
e.tail(levelsum - lumo);
131 out[k] += fac * ((m2.head(lumo) * term(t_occ)).sum() +
132 (m2.tail(levelsum - lumo) * term(t_virt)).sum());
138 double frequency)
const {
140 const double eta2 =
opt_.eta *
opt_.eta;
143 [eta2](
const auto& t) {
return t / (t.square() + eta2); });
148 double frequency)
const {
149 const double eta2 =
opt_.eta *
opt_.eta;
150 double dsigma_domega = 0.0;
152 [eta2](
const auto& t) {
153 return (eta2 - t.square()) / (t.square() + eta2).square();
155 return dsigma_domega;
159 Index gw_level,
const Eigen::VectorXd& frequencies)
const {
160 const Index nfreq = frequencies.size();
161 for (
Index i = 0; i < nfreq; ++i) {
178 double frequency2)
const {
182 const double eta2 =
opt_.eta *
opt_.eta;
185 const Eigen::VectorXd ppm_weight =
ppm_.getPpm_weight();
186 const Eigen::VectorXd ppm_freqs =
ppm_.getPpm_freq();
188 const Eigen::VectorXd RPAEnergies =
rpa_.getRPAInputEnergies();
190 for (
Index i_aux = 0; i_aux < auxsize; i_aux++) {
193 if (ppm_weight(i_aux) < 1.e-9) {
196 const double ppm_freq = ppm_freqs(i_aux);
197 const double fac = 0.25 * ppm_weight(i_aux) * ppm_freq;
198 const Eigen::MatrixXd& Mmn1 =
Mmn_[gw_level1 + qpmin_offset];
199 const Eigen::MatrixXd& Mmn2 =
Mmn_[gw_level2 + qpmin_offset];
200 const Eigen::ArrayXd Mmn1xMmn2 =
201 Mmn1.col(i_aux).cwiseProduct(Mmn2.col(i_aux));
202 Eigen::ArrayXd temp1 = RPAEnergies;
203 temp1.segment(0, lumo) -= ppm_freq;
204 temp1.segment(lumo, levelsum - lumo) += ppm_freq;
205 Eigen::ArrayXd temp2 = (frequency2 - temp1);
206 temp1 = (frequency1 - temp1);
208 fac * ((temp1 / (temp1.abs2() + eta2) + temp2 / (temp2.abs2() + eta2)) *
216 const Eigen::VectorXd& frequencies)
const {
220 const double eta2 =
opt_.eta *
opt_.eta;
224 const Eigen::VectorXd& ppm_weight =
ppm_.getPpm_weight();
225 const Eigen::VectorXd& ppm_freqs =
ppm_.getPpm_freq();
226 const Eigen::ArrayXd energies =
rpa_.getRPAInputEnergies().array();
230 const Eigen::MatrixXd A =
232 const Eigen::MatrixXd& M =
Mmn_[m + qpmin_offset];
233 X.resize(levelsum, auxsize);
234 const double w = frequencies(m);
235 Eigen::ArrayXd t(levelsum);
236 for (
Index i_aux = 0; i_aux < auxsize; ++i_aux) {
237 if (ppm_weight(i_aux) < 1.e-9) {
238 X.col(i_aux).setZero();
241 const double ppm_freq = ppm_freqs(i_aux);
242 const double fac = 0.25 * ppm_weight(i_aux) * ppm_freq;
244 t.head(lumo) += ppm_freq;
245 t.tail(levelsum - lumo) -= ppm_freq;
247 (fac * M.col(i_aux).array() * t / (t.abs2() + eta2)).matrix();
250 Eigen::MatrixXd result = A + A.transpose();
251 result.diagonal().setZero();
double CalcCorrelationOffDiagElement(Index gw_level1, Index gw_level2, double frequency1, double frequency2) const final
Eigen::VectorXd screening_energies_
DiagPoleForm PoleForm(Index gw_level) 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_
ScreeningData ScreeningDump(const Eigen::VectorXd &nu) const final
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.
Eigen::MatrixXd frame_eps_inv_imag
Eigen::VectorXd frame_weights
Eigen::MatrixXd frame_moments