votca 2026-dev
Loading...
Searching...
No Matches
gw.h
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#pragma once
21#ifndef VOTCA_XTP_GW_H
22#define VOTCA_XTP_GW_H
23
24#include <unordered_set>
25
26// Local VOTCA includes
27#include "logger.h"
28#include "orbitals.h"
29#include "qp_solver_utils.h"
30#include "rpa.h"
31#include "sigma_base.h"
32#include "threecenter.h"
33
34namespace votca {
35namespace xtp {
36
37class GW {
38
43
44 public:
45 GW(Logger& log, TCMatrix_gwbse& Mmn, const Eigen::MatrixXd& vxc,
46 const Eigen::VectorXd& dft_energies)
47 : log_(log),
48 Mmn_(Mmn),
49 vxc_(vxc),
50 dft_energies_(dft_energies),
51 rpa_(log, Mmn) {};
52
53 struct options {
59 double eta;
60 double g_sc_limit;
64 double shift = 0;
65 double ScaHFX = 0.0;
66 std::string sigma_integration;
67 Index reset_3c; // how often the 3c integrals in iterate should be
68 // rebuilt
69 std::string qp_solver;
70 double qp_solver_alpha = 0.75;
71 // Legacy aliases from the original grid-search implementation.
72 // They used to define both the total QP window and the scan resolution at
73 // the same time. The new implementation keeps them only so that old XML
74 // files and existing tests still work; configuration code maps them onto
75 // the decoupled controls below.
77 double qp_grid_spacing = 0.0;
78
79 // Decoupled QP search controls:
80 // - qp_full_window_half_width defines the outer full search interval
81 // - qp_dense_spacing defines the dense scan used for robust sign changes
82 // - qp_adaptive_shell_width / count define the outward shell search
83 // All values are normalized in configure(); negative values mean "unset"
84 // and trigger either legacy mapping or robust defaults.
85 double qp_full_window_half_width = -1.0; // Ha; <=0 means "unset"
86 double qp_dense_spacing = -1.0; // Ha; <=0 means "unset"
87 double qp_adaptive_shell_width = -1.0; // Ha; <=0 means "unset"
88 Index qp_adaptive_shell_count = 0; // 0 means "use shell width"
89
90 Index gw_mixing_order; // mixing order
91 double gw_mixing_alpha; // mixing alpha, also linear mixing
92 std::string quadrature_scheme; // Kind of Gaussian-quadrature scheme to use
93 Index order; // only needed for complex integration sigma CDA
94 double alpha; // smooth tail in complex integration sigma CDA
95 bool qp_restrict_search = true;
96 double qp_zero_margin = 1e-6;
97 double qp_virtual_min_energy = -0.1;
98 std::string qp_root_finder = "bisection";
99 std::string qp_grid_search_mode = "adaptive_with_dense_fallback";
100
101 // QSGW options
102 // When true, run quasiparticle self-consistent GW instead of evGW.
103 // The three-centre integrals are rotated at each iteration so that W and
104 // Sigma are evaluated in the basis of the current QP wavefunctions.
105 bool do_qsgw = false;
107 double qsgw_sc_limit = 1e-5; // Ha; convergence threshold on QP energies
108
109 // Maximum allowed perturbative QP correction for virtual states to be
110 // included in the QSGW self-consistency loop. Virtual states with
111 // |e_QP - e_DFT| > qsgw_max_virt_correction are excluded from the QSGW
112 // window and kept at their perturbative QP energies (DFT-MO wavefunctions).
113 // This prevents pathological high-energy basis-set artefact states from
114 // destabilising the QSGW rotation. Occupied states are never excluded.
115 // Default: 0.5 Ha (13.6 eV, 1 Rydberg) -- corrections above this are
116 // unlikely to be physically meaningful for typical molecular systems.
117 // Set to a large value (e.g. 1e10) to disable the threshold entirely.
118 double qsgw_max_virt_correction = 0.5; // Ha
119 };
120
121 void configure(const options& opt);
122
123 Eigen::VectorXd getGWAResults() const;
124 // Calculates the diagonal elements up to self consistency
126
127 // Calculated offdiagonal elements as well
128 void CalculateHQP();
129
146 void CalculateQSGW();
147
150 const Eigen::MatrixXd& getQSGWRotation() const { return qsgw_rotation_; }
151
153 const Eigen::VectorXd& getQSGWSeedEnergies() const {
154 return qsgw_seed_energies_;
155 }
156
165 void PrintQSGW_Energies(const std::string& seed_label,
166 const Eigen::VectorXd& seed_energies,
167 const Eigen::VectorXd& qsgw_energies) const;
168
178 void PrintQSGW_Composition(double threshold = 0.01) const;
179
180 Eigen::MatrixXd getHQP() const;
181
182 // Diagonalize QP particle Hamiltonian
183 Eigen::SelfAdjointEigenSolver<Eigen::MatrixXd> DiagonalizeQPHamiltonian()
184 const;
185
186 void PlotSigma(std::string filename, Index steps, double spacing,
187 std::string states) const;
188
189 Eigen::VectorXd RPAInputEnergies() const {
190 return rpa_.getRPAInputEnergies();
191 }
192
193 private:
195
196 Eigen::MatrixXd Sigma_x_;
197 Eigen::MatrixXd Sigma_c_;
198 Eigen::MatrixXd qsgw_rotation_; // accumulated U: DFT MOs -> QSGW QP
199 // wavefunctions
200 Eigen::VectorXd qsgw_seed_energies_; // evGW/G0W0 energies used as QSGW seed
201 // Merged QSGW+seed energies for the full QP window. Set by CalculateQSGW()
202 // when the virtual window is trimmed. getGWAResults() returns this when
203 // non-empty, bypassing the sigma-matrix recomputation which would be wrong
204 // for the excluded levels.
205 Eigen::VectorXd qsgw_final_energies_;
206
208
209 std::unique_ptr<Sigma_base> sigma_ = nullptr;
212 const Eigen::MatrixXd& vxc_;
213 const Eigen::VectorXd& dft_energies_;
214
216
218 // small class which calculates f(w) with and df/dw(w)
219 // f=Sigma_c(w)+offset-w
220 // offset= e_dft+Sigma_x-Vxc
221 class QPFunc {
222 public:
223 QPFunc(Index gw_level, const Sigma_base& sigma, double offset)
224 : gw_level_(gw_level), offset_(offset), sigma_c_func_(sigma) {}
225
226 std::pair<double, double> operator()(double frequency) const {
227 std::pair<double, double> result;
228 result.first = value(frequency, EvalStage::Other);
229 result.second = deriv(frequency);
230 return result;
231 }
232
233 double sigma(double frequency, EvalStage stage = EvalStage::Other) const {
234 const std::uint64_t key = FrequencyKey(frequency);
235
236 auto insert_result = seen_frequencies_.insert(key);
237 if (!insert_result.second) {
238 ++stats_.sigma_repeat_calls;
239 } else {
240 ++stats_.sigma_unique_frequencies;
241 }
242
243 CountSigmaStage(stage);
244 return sigma_c_func_.CalcCorrelationDiagElement(gw_level_, frequency);
245 }
246
247 double value(double frequency, EvalStage stage = EvalStage::Other) const {
248 return sigma(frequency, stage) + offset_ - frequency;
249 }
250
251 double deriv(double frequency) const {
252 ++stats_.deriv_calls;
253 return sigma_c_func_.CalcCorrelationDiagElementDerivative(gw_level_,
254 frequency) -
255 1.0;
256 }
257
258 const QPStats& GetStats() const { return stats_; }
259
260 private:
261 static std::uint64_t FrequencyKey(double x) {
262 std::uint64_t key = 0;
263 static_assert(sizeof(double) == sizeof(std::uint64_t),
264 "Unexpected double size");
265 std::memcpy(&key, &x, sizeof(double));
266 return key;
267 }
268
269 void CountSigmaStage(EvalStage stage) const {
270 switch (stage) {
271 case EvalStage::Scan:
272 ++stats_.sigma_scan_calls;
273 break;
274 case EvalStage::Refine:
275 ++stats_.sigma_refine_calls;
276 break;
277 case EvalStage::Derivative:
278 ++stats_.sigma_derivative_calls;
279 break;
280 case EvalStage::Other:
281 default:
282 ++stats_.sigma_other_calls;
283 break;
284 }
285 }
286
288 double offset_;
290
291 mutable std::unordered_set<std::uint64_t> seen_frequencies_;
293 };
294
295 double CalcHomoLumoShift(Eigen::VectorXd frequencies) const;
296 Eigen::VectorXd ScissorShift_DFTlevel(
297 const Eigen::VectorXd& dft_energies) const;
298 void PrintQP_Energies(const Eigen::VectorXd& qp_diag_energies) const;
299 void PrintGWA_Energies() const;
300
301 Eigen::VectorXd SolveQP(const Eigen::VectorXd& frequencies) const;
302 boost::optional<double> SolveQP_Grid(double intercept0, double frequency0,
303 Index gw_level,
304 QPStats* stats = nullptr) const;
305
306 boost::optional<double> SolveQP_Grid_Windowed(
307 double intercept0, double frequency0, Index gw_level, double left_limit,
308 double right_limit, bool allow_rejected_return = true,
309 QPStats* stats = nullptr) const;
310
311 boost::optional<double> SolveQP_Grid_Windowed_Adaptive(
312 double intercept0, double frequency0, Index gw_level, double left_limit,
313 double right_limit, bool allow_rejected_return = true,
314 QPStats* stats = nullptr) const;
315
316 boost::optional<double> SolveQP_Grid_Windowed_Dense(
317 double intercept0, double frequency0, Index gw_level, double left_limit,
318 double right_limit, bool allow_rejected_return = true,
319 QPStats* stats = nullptr) const;
320
321 boost::optional<double> SolveQP_FixedPoint(double intercept0,
322 double frequency0, Index gw_level,
323 QPStats* stats = nullptr) const;
324 boost::optional<double> SolveQP_Linearisation(double intercept0,
325 double frequency0,
326 Index gw_level,
327 QPStats* stats = nullptr) const;
328 bool Converged(const Eigen::VectorXd& e1, const Eigen::VectorXd& e2,
329 double epsilon) const;
330
331 boost::optional<QPRootCandidate> RefineQPInterval(
332 double lowerbound, double f_lowerbound, double upperbound,
333 double f_upperbound, const QPFunc& f, double reference) const;
334};
335} // namespace xtp
336} // namespace votca
337
338#endif // VOTCA_XTP_GW_H
void CountSigmaStage(EvalStage stage) const
Definition gw.h:269
double value(double frequency, EvalStage stage=EvalStage::Other) const
Definition gw.h:247
double sigma(double frequency, EvalStage stage=EvalStage::Other) const
Definition gw.h:233
const Sigma_base & sigma_c_func_
Definition gw.h:289
const QPStats & GetStats() const
Definition gw.h:258
std::unordered_set< std::uint64_t > seen_frequencies_
Definition gw.h:291
static std::uint64_t FrequencyKey(double x)
Definition gw.h:261
QPFunc(Index gw_level, const Sigma_base &sigma, double offset)
Definition gw.h:223
double deriv(double frequency) const
Definition gw.h:251
std::pair< double, double > operator()(double frequency) const
Definition gw.h:226
boost::optional< double > SolveQP_Grid_Windowed(double intercept0, double frequency0, Index gw_level, double left_limit, double right_limit, bool allow_rejected_return=true, QPStats *stats=nullptr) const
Definition gw.cc:623
void PlotSigma(std::string filename, Index steps, double spacing, std::string states) const
Definition gw.cc:1133
Index qptotal_
Definition gw.h:194
const Eigen::VectorXd & getQSGWSeedEnergies() const
Return the seed (G0W0/evGW) energies that QSGW started from.
Definition gw.h:153
Eigen::SelfAdjointEigenSolver< Eigen::MatrixXd > DiagonalizeQPHamiltonian() const
Definition gw.cc:73
void PrintGWA_Energies() const
Definition gw.cc:80
RPA rpa_
Definition gw.h:217
boost::optional< QPRootCandidate > RefineQPInterval(double lowerbound, double f_lowerbound, double upperbound, double f_upperbound, const QPFunc &f, double reference) const
void PrintQSGW_Energies(const std::string &seed_label, const Eigen::VectorXd &seed_energies, const Eigen::VectorXd &qsgw_energies) const
Print a two-column comparison of seed (G0W0 or evGW) vs converged QSGW quasiparticle energies.
Definition gw.cc:156
void CalculateQSGW()
Run quasiparticle self-consistent GW (QSGW).
Definition gw.cc:798
bool Converged(const Eigen::VectorXd &e1, const Eigen::VectorXd &e2, double epsilon) const
Definition gw.cc:759
void configure(const options &opt)
Definition gw.cc:35
boost::optional< double > SolveQP_Grid_Windowed_Adaptive(double intercept0, double frequency0, Index gw_level, double left_limit, double right_limit, bool allow_rejected_return=true, QPStats *stats=nullptr) const
Definition gw.cc:433
options opt_
Definition gw.h:207
Eigen::MatrixXd getHQP() const
Definition gw.cc:67
Eigen::VectorXd SolveQP(const Eigen::VectorXd &frequencies) const
Definition gw.cc:323
TCMatrix_gwbse & Mmn_
Definition gw.h:211
Index gw_sc_iteration_
Definition gw.h:215
qp_solver::EvalStage EvalStage
Definition gw.h:39
qp_solver::Stats QPStats
Definition gw.h:40
boost::optional< double > SolveQP_Grid_Windowed_Dense(double intercept0, double frequency0, Index gw_level, double left_limit, double right_limit, bool allow_rejected_return=true, QPStats *stats=nullptr) const
Definition gw.cc:503
Eigen::MatrixXd Sigma_c_
Definition gw.h:197
qp_solver::RootCandidate QPRootCandidate
Definition gw.h:41
void PrintQSGW_Composition(double threshold=0.01) const
Print the dominant DFT-KS orbital contributions to each converged QSGW quasiparticle state.
Definition gw.cc:113
Eigen::VectorXd qsgw_seed_energies_
Definition gw.h:200
const Eigen::VectorXd & dft_energies_
Definition gw.h:213
std::unique_ptr< Sigma_base > sigma_
Definition gw.h:209
void CalculateHQP()
Definition gw.cc:772
Eigen::VectorXd qsgw_final_energies_
Definition gw.h:205
Logger & log_
Definition gw.h:210
Eigen::VectorXd getGWAResults() const
Definition gw.cc:312
Eigen::VectorXd RPAInputEnergies() const
Definition gw.h:189
qp_solver::WindowDiagnostics QPWindowDiagnostics
Definition gw.h:42
double CalcHomoLumoShift(Eigen::VectorXd frequencies) const
Definition gw.cc:60
boost::optional< double > SolveQP_Grid(double intercept0, double frequency0, Index gw_level, QPStats *stats=nullptr) const
Definition gw.cc:677
const Eigen::MatrixXd & vxc_
Definition gw.h:212
void PrintQP_Energies(const Eigen::VectorXd &qp_diag_energies) const
Definition gw.cc:183
const Eigen::MatrixXd & getQSGWRotation() const
Definition gw.h:150
boost::optional< double > SolveQP_FixedPoint(double intercept0, double frequency0, Index gw_level, QPStats *stats=nullptr) const
Definition gw.cc:741
Eigen::VectorXd ScissorShift_DFTlevel(const Eigen::VectorXd &dft_energies) const
Definition gw.cc:210
GW(Logger &log, TCMatrix_gwbse &Mmn, const Eigen::MatrixXd &vxc, const Eigen::VectorXd &dft_energies)
Definition gw.h:45
Eigen::MatrixXd Sigma_x_
Definition gw.h:196
boost::optional< double > SolveQP_Linearisation(double intercept0, double frequency0, Index gw_level, QPStats *stats=nullptr) const
Definition gw.cc:412
void CalculateGWPerturbation()
Definition gw.cc:218
Eigen::MatrixXd qsgw_rotation_
Definition gw.h:198
Logger is used for thread-safe output of messages.
Definition logger.h:164
Provides a means for comparing floating point numbers.
Definition basebead.h:33
Eigen::Index Index
Definition types.h:26
double qp_full_window_half_width
Definition gw.h:85
double qsgw_sc_limit
Definition gw.h:107
double qsgw_max_virt_correction
Definition gw.h:118
Index qp_adaptive_shell_count
Definition gw.h:88
double qp_adaptive_shell_width
Definition gw.h:87
double qp_solver_alpha
Definition gw.h:70
double qp_zero_margin
Definition gw.h:96
double gw_sc_limit
Definition gw.h:62
std::string qp_grid_search_mode
Definition gw.h:99
double qp_virtual_min_energy
Definition gw.h:97
Index gw_mixing_order
Definition gw.h:90
Index gw_sc_max_iterations
Definition gw.h:63
Index qp_grid_steps
Definition gw.h:76
std::string quadrature_scheme
Definition gw.h:92
std::string qp_solver
Definition gw.h:69
Index g_sc_max_iterations
Definition gw.h:61
double qp_grid_spacing
Definition gw.h:77
double g_sc_limit
Definition gw.h:60
std::string qp_root_finder
Definition gw.h:98
double gw_mixing_alpha
Definition gw.h:91
std::string sigma_integration
Definition gw.h:66
double qp_dense_spacing
Definition gw.h:86
Index qsgw_max_iterations
Definition gw.h:106
bool qp_restrict_search
Definition gw.h:95