votca 2026-dev
Loading...
Searching...
No Matches
sigma_exact_uks.cc
Go to the documentation of this file.
1/*
2 * Copyright 2009-2020 The VOTCA Development Team
3 * (http://www.votca.org)
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License")
6 *
7 * You may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 *
18 */
19
20#include "sigma_exact_uks.h"
21
22#include <algorithm>
23#include <iomanip>
24#include <sstream>
25#include <utility>
26#include <vector>
27
28#include "votca/xtp/rpa_uks.h"
30#include "votca/xtp/vc2index.h"
31
32namespace {} // namespace
33
34namespace votca {
35namespace xtp {
36
38
39 // Build Coulomb-active screening modes in the auxiliary basis from the full
40 // unrestricted H2p eigenvectors. This suppresses numerically dark / spin-like
41 // modes that can appear in the explicit alpha+beta transition basis but
42 // should not contribute to the screened Coulomb interaction W.
43 const Eigen::VectorXd* cached_omegas = nullptr;
44 const std::vector<Eigen::VectorXd>* cached_modes = nullptr;
45 rpa_.GetCachedScreeningModes(cached_omegas, cached_modes);
46
47 rpa_omegas_ = *cached_omegas;
48 screening_modes_ = *cached_modes;
49 residues_ = std::vector<Eigen::MatrixXd>(qptotal_);
50#pragma omp parallel for schedule(dynamic)
51 for (Index gw_level = 0; gw_level < qptotal_; gw_level++) {
52 const Index qpoffset = opt_.qpmin - opt_.rpamin;
53 const Eigen::MatrixXd& Mmn_i = Mmn_[gw_level + qpoffset];
54
55 Eigen::MatrixXd res = Eigen::MatrixXd::Zero(rpatotal_, rpa_omegas_.size());
56 for (Index s = 0; s < rpa_omegas_.size(); s++) {
57 res.col(s) = Mmn_i * screening_modes_[s];
58 }
59 residues_[gw_level] = std::move(res);
60 }
61}
62
64 double frequency) const {
65 const double eta2 = opt_.eta * opt_.eta;
66 const Index lumo = opt_.homo + 1;
67 const Index n_occ = lumo - opt_.rpamin;
68 const Index n_unocc = opt_.rpamax - opt_.homo;
69 const Eigen::VectorXd& energies = getSpinRPAInputEnergies();
70
71 double sigma = 0.0;
72 for (Index s = 0; s < rpa_omegas_.size(); s++) {
73 const double eigenvalue = rpa_omegas_(s);
74 const Eigen::ArrayXd res_12 = residues_[gw_level].col(s).cwiseAbs2();
75
76 Eigen::ArrayXd temp = -energies.array() + frequency;
77 temp.segment(0, n_occ) += eigenvalue;
78 temp.segment(n_occ, n_unocc) -= eigenvalue;
79
80 const Eigen::ArrayXd denom = temp.abs2() + eta2;
81 sigma += (res_12 * temp / denom).sum();
82 }
83 return sigma;
84}
85
87 Index gw_level, double frequency) const {
88 const double eta2 = opt_.eta * opt_.eta;
89 const Index lumo = opt_.homo + 1;
90 const Index n_occ = lumo - opt_.rpamin;
91 const Index n_unocc = opt_.rpamax - opt_.homo;
92 const Eigen::VectorXd& energies = getSpinRPAInputEnergies();
93
94 double dsigma_domega = 0.0;
95 for (Index s = 0; s < rpa_omegas_.size(); s++) {
96 const double eigenvalue = rpa_omegas_(s);
97 const Eigen::ArrayXd res_12 = residues_[gw_level].col(s).cwiseAbs2();
98
99 Eigen::ArrayXd temp = -energies.array() + frequency;
100 temp.segment(0, n_occ) += eigenvalue;
101 temp.segment(n_occ, n_unocc) -= eigenvalue;
102
103 const Eigen::ArrayXd denom = temp.abs2() + eta2;
104 dsigma_domega += ((eta2 - temp.abs2()) * res_12 / denom.abs2()).sum();
105 }
106 return dsigma_domega;
107}
108
110 Index gw_level2,
111 double frequency1,
112 double frequency2) const {
113 const double eta2 = opt_.eta * opt_.eta;
114 const Index lumo = opt_.homo + 1;
115 const Index n_occ = lumo - opt_.rpamin;
116 const Index n_unocc = opt_.rpamax - opt_.homo;
117 const Eigen::VectorXd& energies = getSpinRPAInputEnergies();
118
119 double sigma_c = 0.0;
120 for (Index s = 0; s < rpa_omegas_.size(); s++) {
121 const double eigenvalue = rpa_omegas_(s);
122 const Eigen::VectorXd& res1 = residues_[gw_level1].col(s);
123 const Eigen::VectorXd& res2 = residues_[gw_level2].col(s);
124 const Eigen::VectorXd res_12 = res1.cwiseProduct(res2);
125
126 Eigen::ArrayXd temp1 = -energies.array();
127 temp1.segment(0, n_occ) += eigenvalue;
128 temp1.segment(n_occ, n_unocc) -= eigenvalue;
129
130 const Eigen::ArrayXd temp2 = temp1 + frequency2;
131 temp1 += frequency1;
132
133 const Eigen::ArrayXd numer1 = res_12.array() * temp1;
134 const Eigen::ArrayXd numer2 = res_12.array() * temp2;
135 const Eigen::ArrayXd denom1 = temp1.abs2() + eta2;
136 const Eigen::ArrayXd denom2 = temp2.abs2() + eta2;
137
138 sigma_c += 0.5 * ((numer1 / denom1) + (numer2 / denom2)).sum();
139 }
140 return sigma_c;
141}
142
143} // namespace xtp
144} // namespace votca
std::vector< Eigen::MatrixXd > residues_
double CalcCorrelationDiagElement(Index gw_level, double frequency) const final
double CalcCorrelationOffDiagElement(Index gw_level1, Index gw_level2, double frequency1, double frequency2) const final
std::vector< Eigen::VectorXd > screening_modes_
double CalcCorrelationDiagElementDerivative(Index gw_level, double frequency) const final
const Eigen::VectorXd & getSpinRPAInputEnergies() const
Charge transport classes.
Definition ERIs.h:28
Provides a means for comparing floating point numbers.
Definition basebead.h:33
Eigen::Index Index
Definition types.h:26