29 const Eigen::MatrixXd& vxc_alpha,
30 const Eigen::MatrixXd& vxc_beta,
31 const Eigen::VectorXd& dft_energies_alpha,
32 const Eigen::VectorXd& dft_energies_beta)
49 rpa_.setOutOfWindowShift(
opt_.out_of_window_shift);
57 throw std::runtime_error(
58 "GW_UKS currently supports only implemented unrestricted sigma "
59 "evaluators. At present this is 'ppm', 'cda', and 'exact'.");
81 auto print_spin_ranges = [&](
Spin spin,
Index homo) {
82 const Index lumo = homo + 1;
84 const Index n_occ_rpa =
85 (
opt_.rpamin <= homo) ? (homo -
opt_.rpamin + 1) : 0;
86 const Index n_virt_rpa =
87 (lumo <=
opt_.rpamax) ? (
opt_.rpamax - lumo + 1) : 0;
90 const Index qp_occ_max = std::min(
opt_.qpmax, homo);
91 const Index n_occ_qp =
92 (qp_occ_min <= qp_occ_max) ? (qp_occ_max - qp_occ_min + 1) : 0;
94 const Index qp_virt_min = std::max(
opt_.qpmin, lumo);
96 const Index n_virt_qp =
97 (qp_virt_min <= qp_virt_max) ? (qp_virt_max - qp_virt_min + 1) : 0;
101 <<
" effective ranges: HOMO=" << homo <<
" LUMO=" << lumo
102 <<
" | RPA occ[" <<
opt_.rpamin <<
":" << homo <<
"]"
103 <<
" virt[" << lumo <<
":" <<
opt_.rpamax <<
"]"
104 <<
" (#occ=" << n_occ_rpa <<
", #virt=" << n_virt_rpa <<
")"
105 <<
" | GW occ[" << qp_occ_min <<
":" << qp_occ_max <<
"]"
106 <<
" virt[" << qp_virt_min <<
":" << qp_virt_max <<
"]"
107 <<
" (#occ=" << n_occ_qp <<
", #virt=" << n_virt_qp <<
")"
114 if (
opt_.sigma_integration ==
"ppm") {
118 if (ppm_a ==
nullptr || ppm_b ==
nullptr) {
119 throw std::runtime_error(
120 "GW_UKS: expected Sigma_PPM_UKS evaluators for "
121 "sigma_integration=ppm");
125 ppm_b->SetSharedPPM(
ppm_);
161 if (level ==
Homo(spin)) {
163 }
else if (level ==
Homo(spin) + 1) {
171 return (level <=
Homo(spin)) ?
"occ" :
"virt";
175 const Eigen::VectorXd& dft_energies,
Index homo)
const {
176 Eigen::VectorXd shifted_energies = dft_energies;
177 shifted_energies.segment(homo + 1, dft_energies.size() - homo - 1).array() +=
179 return shifted_energies;
186 const double DFTgap = dft(homo + 1) - dft(homo);
188 frequencies(homo + 1 -
opt_.qpmin) - frequencies(homo -
opt_.qpmin);
189 return QPgap - DFTgap;
201 <<
" Calculated spin-resolved Hartree exchange contribution"
204 Eigen::VectorXd dft_shifted_alpha =
206 Eigen::VectorXd dft_shifted_beta =
211 <<
" Scissor shifting alpha/beta DFT energies by: " <<
opt_.shift
212 <<
" Hrt" << std::flush;
214 rpa_.setRPAInputEnergies(
215 dft_shifted_alpha.segment(
opt_.rpamin,
opt_.rpamax -
opt_.rpamin + 1),
216 dft_shifted_beta.segment(
opt_.rpamin,
opt_.rpamax -
opt_.rpamin + 1));
218 Eigen::VectorXd frequencies_alpha =
220 Eigen::VectorXd frequencies_beta =
229 Eigen::VectorXd qp_solution_alpha = frequencies_alpha;
230 Eigen::VectorXd qp_solution_beta = frequencies_beta;
231 Eigen::VectorXd rpa_solved_alpha =
rpa_.getRPAInputEnergiesAlpha();
232 Eigen::VectorXd rpa_solved_beta =
rpa_.getRPAInputEnergiesBeta();
235 auto rpa_both = [
this]() {
236 const Eigen::VectorXd& a =
rpa_.getRPAInputEnergiesAlpha();
237 const Eigen::VectorXd& b =
rpa_.getRPAInputEnergiesBeta();
238 Eigen::VectorXd both(a.size() + b.size());
244 opt_.screening_update_ratio,
245 opt_.screening_update_max_inner);
246 bool rebuild_screening =
true;
247 Index mixing_iteration = 0;
248 Index n_iterations = 0;
254 bool tracking_verified =
false;
255 bool verifying =
false;
257 for (
Index i_gw = 0; i_gw <
opt_.gw_sc_max_iterations; ++i_gw) {
262 if (
opt_.reset_3c > 0 && i_gw %
opt_.reset_3c == 0 && i_gw != 0) {
263 Mmn_.alpha.Rebuild();
266 <<
TimeStamp() <<
" Rebuilding alpha/beta 3c integrals" << std::flush;
267 rebuild_screening =
true;
270 if (rebuild_screening) {
275 if (
opt_.sigma_integration ==
"ppm") {
276 ppm_.PPM_construct_parameters(
rpa_);
277 if (
ppm_.InvalidModes() > 0) {
280 <<
" PPM modes with negative squared frequency (|.| used)"
286 screening.
Built(rpa_both());
293 mixing_iteration = 0;
299 <<
TimeStamp() <<
" Calculated unrestricted screening via RPA; "
303 const bool mix =
opt_.gw_mixing_order > 0 && mixing_iteration > 0;
309 const Eigen::VectorXd qp_input_alpha = frequencies_alpha;
310 const Eigen::VectorXd qp_input_beta = frequencies_beta;
313 qp_solution_alpha = frequencies_alpha;
314 qp_solution_beta = frequencies_beta;
315 rpa_solved_alpha =
rpa_.getRPAInputEnergiesAlpha();
316 rpa_solved_beta =
rpa_.getRPAInputEnergiesBeta();
320 if (
opt_.gw_sc_max_iterations > 1) {
321 Eigen::VectorXd rpa_alpha_old =
rpa_.getRPAInputEnergiesAlpha();
322 Eigen::VectorXd rpa_beta_old =
rpa_.getRPAInputEnergiesBeta();
327 frequencies_alpha = mixing_alpha.
MixHistory();
332 frequencies_alpha, frequencies_beta,
336 <<
TimeStamp() <<
" GW_Iteration:" << i_gw <<
" Shift_alpha[Hrt]:"
338 <<
" Shift_beta[Hrt]:"
345 const double residual =
346 std::max((qp_solution_alpha - qp_input_alpha).cwiseAbs().maxCoeff(),
347 (qp_solution_beta - qp_input_beta).cwiseAbs().maxCoeff());
349 <<
"input) max=" << residual << std::flush;
351 <<
TimeStamp() <<
" Largest QP residuals alpha (level: input -> "
357 <<
TimeStamp() <<
" Largest QP residuals beta: "
363 screening.
Decide(residual, rpa_both(),
opt_.gw_sc_limit, &drift);
366 <<
TimeStamp() <<
" Change since the screening was built: " << drift
367 <<
" Hrt after " << screening.
inner() <<
" iteration(s)"
372 if (verifying && roots_before_alpha.size() ==
qptotal_ &&
373 roots_before_beta.size() ==
qptotal_) {
375 std::vector<Index> moved_alpha;
376 std::vector<Index> moved_beta;
379 10.0 *
opt_.gw_sc_limit) {
380 moved_alpha.push_back(l +
opt_.qpmin);
383 10.0 *
opt_.gw_sc_limit) {
384 moved_beta.push_back(l +
opt_.qpmin);
387 if ((!moved_alpha.empty() || !moved_beta.empty()) &&
391 <<
TimeStamp() <<
" QP root tracking: the full search chose "
392 <<
"other roots for levels alpha ["
395 <<
"]; continuing with the full search" << std::flush;
400 !tracking_verified && i_gw > 0) {
403 tracking_verified =
true;
405 rebuild_screening =
false;
408 <<
" QP root tracking converged; verifying with a full search"
410 if (i_gw <
opt_.gw_sc_max_iterations - 1) {
416 <<
TimeStamp() <<
" Converged after " << i_gw + 1
417 <<
" unrestricted GW iterations." << std::flush;
419 }
else if (i_gw ==
opt_.gw_sc_max_iterations - 1) {
422 <<
" WARNING! UKS GW-self-consistency cycle not converged after "
423 <<
opt_.gw_sc_max_iterations <<
" iterations." << std::flush;
432 if (
opt_.gw_sc_max_iterations > 1) {
434 <<
TimeStamp() <<
" evGW (UKS): " << n_iterations <<
" QP iterations, "
435 << screening.
builds() <<
" screening builds ("
437 << (
opt_.qp_root_tracking
438 ?
"; root tracking solved " +
440 std::to_string(2 * n_iterations *
qptotal_) +
441 " level solves locally"
450 const Eigen::VectorXd rpa_next_alpha =
rpa_.getRPAInputEnergiesAlpha();
451 const Eigen::VectorXd rpa_next_beta =
rpa_.getRPAInputEnergiesBeta();
452 rpa_.setRPAInputEnergies(rpa_solved_alpha, rpa_solved_beta);
456 rpa_.setRPAInputEnergies(rpa_next_alpha, rpa_next_beta);
472 return rpa_.getRPAInputEnergiesAlpha();
475 return rpa_.getRPAInputEnergiesBeta();
481 for (
const auto& c : list) {
482 n += c.competing ? 1 : 0;
488 <<
" QP level(s) with two roots of comparable weight "
489 "(second Z at least half the largest):"
491 for (
Index i = 0; i <
Index(list.size()); ++i) {
492 const auto& c = list[std::size_t(i)];
495 << (boost::format(
" Level = %1$4d chosen %2$+1.6f (Z = %3$.3f), "
496 "other %4$+1.6f (Z = %5$.3f)") %
497 (i +
opt_.qpmin) % c.omega % c.Z % c.omega_alt % c.Z_alt)
505 const Eigen::VectorXd& frequencies)
const {
508 const Eigen::VectorXd intercepts =
510 SigmaX(spin).diagonal() -
Vxc(spin).diagonal();
512 Eigen::VectorXd frequencies_new = frequencies;
520 const std::size_t si = (spin ==
Spin::Alpha) ? 0 : 1;
521 const bool track =
opt_.qp_root_tracking;
522 const bool use_tracked =
524 Eigen::VectorXd roots_new = frequencies;
525 Eigen::VectorXd Z_new = Eigen::VectorXd::Zero(
qptotal_);
528#pragma omp parallel for schedule(dynamic) num_threads(use_threads)
530 const double initial_f = frequencies[gw_level];
531 const double intercept = intercepts[gw_level];
533 boost::optional<double> newf;
543 const double halfwidth = std::clamp(4.0 * moved, 0.01, 0.1);
550 fqp, center, halfwidth,
tracked_Z_[si](gw_level), 0.5, solver_opt,
551 opt_.qp_root_finder ==
"brent");
561 if (!newf &&
opt_.qp_solver ==
"fixedpoint") {
567 frequencies_new[gw_level] = newf.value();
569 newf =
SolveQP_Grid(spin, intercept, initial_f, gw_level, &grid_stats);
571 frequencies_new[gw_level] = newf.value();
576 frequencies_new[gw_level] = newf.value();
581 roots_new[gw_level] = newf.value();
584 const double d = fqp.
deriv(newf.value());
585 Z_root = (std::abs(d) > 1
e-14) ? -1.0 / d : 0.0;
587 Z_new[gw_level] = Z_root;
594 total_stats.
Add(fixed_stats);
595 total_stats.
Add(grid_stats);
596 total_stats.
Add(lin_stats);
598 const Index mo_level =
opt_.qpmin + gw_level;
601 <<
" QP stats " <<
LevelLabel(spin, mo_level) <<
" mo=" << mo_level
617 ? Eigen::VectorXd((roots_new -
tracked_root_[si]).cwiseAbs())
623 return frequencies_new;
631 boost::optional<double> newf = boost::none;
637 fqp.
value(frequency0, EvalStage::Other),
638 fqp.
deriv(frequency0));
640 if (stats !=
nullptr) {
648 double frequency0,
Index gw_level,
652 const double range =
opt_.qp_full_window_half_width;
654 const double full_left_limit = frequency0 - range;
655 const double full_right_limit = frequency0 + range;
657 double restricted_left_limit = full_left_limit;
658 double restricted_right_limit = full_right_limit;
660 bool use_restricted_window =
false;
662 if (
opt_.qp_restrict_search) {
663 const Index mo_level = gw_level +
opt_.qpmin;
664 const bool is_occupied = (mo_level <=
Homo(spin));
667 restricted_right_limit = std::min(full_right_limit, -
opt_.qp_zero_margin);
669 restricted_left_limit =
670 std::max(full_left_limit,
opt_.qp_virtual_min_energy);
673 const double tol = 1
e-12;
674 use_restricted_window =
675 (std::abs(restricted_left_limit - full_left_limit) > tol) ||
676 (std::abs(restricted_right_limit - full_right_limit) > tol);
679 if (use_restricted_window && restricted_left_limit < restricted_right_limit) {
682 restricted_left_limit, restricted_right_limit,
694 <<
" Restricted QP search failed for "
696 << restricted_left_limit <<
", " << restricted_right_limit
697 <<
"], forcing full dense window [" << full_left_limit <<
", "
698 << full_right_limit <<
"]" << std::flush;
703 full_left_limit, full_right_limit,
true,
708 full_left_limit, full_right_limit,
true, stats);
712 Spin spin,
double intercept0,
double frequency0,
Index gw_level,
713 double left_limit,
double right_limit,
bool allow_rejected_return,
732 std::vector<QPRootCandidate> accepted_roots;
733 std::vector<QPRootCandidate> rejected_roots;
735 bool use_brent =
false;
736 if (
opt_.qp_root_finder ==
"brent") {
742 &wdiag, &accepted_roots, &rejected_roots, use_brent);
747 if (accepted_roots.empty() && rejected_roots.empty()) {
749 <<
" No roots found for " <<
LevelLabel(spin,
opt_.qpmin + gw_level)
751 << std::max(left_limit, std::min(right_limit, frequency0))
764 if (stats !=
nullptr) {
768 if (!accepted_roots.empty()) {
775 if (!rejected_roots.empty() && !allow_rejected_return) {
781 <<
" produced only rejected roots in [" << left_limit <<
", "
782 << right_limit <<
"], forcing wider retry" << std::flush;
792 Spin spin,
double intercept0,
double frequency0,
Index gw_level,
793 double left_limit,
double right_limit,
bool allow_rejected_return,
812 const bool use_brent = (
opt_.qp_root_finder ==
"brent");
814 std::vector<QPRootCandidate> accepted_roots;
815 std::vector<QPRootCandidate> rejected_roots;
816 std::vector<std::pair<double, double>> roots;
818 if (left_limit < right_limit) {
819 double freq_prev = left_limit;
820 double targ_prev = fqp.
value(freq_prev, EvalStage::Scan);
825 const Index n_steps = std::max<Index>(
826 2,
static_cast<Index>(
827 std::ceil((right_limit - left_limit) /
opt_.qp_dense_spacing)) +
830 for (
Index i_node = 1; i_node < n_steps; ++i_node) {
832 (i_node == n_steps - 1)
834 : std::min(right_limit, left_limit +
static_cast<double>(i_node) *
835 opt_.qp_dense_spacing);
837 const double targ = fqp.
value(freq, EvalStage::Scan);
839 if (targ_prev * targ < 0.0) {
842 frequency0, solver_opt, use_brent);
844 roots.emplace_back(cand->omega, cand->Z);
845 if (cand->accepted) {
846 accepted_roots.push_back(*cand);
848 rejected_roots.push_back(*cand);
861 if (accepted_roots.empty() && rejected_roots.empty()) {
864 <<
" found no roots in [" << left_limit <<
", " << right_limit
865 <<
"]" << std::flush;
869 <<
" roots (omega:Z)\n\t\t";
870 for (
const auto& root : roots) {
872 << root.second <<
" ";
879 if (stats !=
nullptr) {
883 if (!accepted_roots.empty()) {
889 if (!rejected_roots.empty()) {
890 if (!allow_rejected_return) {
896 <<
" produced only rejected roots in [" << left_limit <<
", "
897 << right_limit <<
"], forcing wider retry" << std::flush;
902 auto least_bad = std::max_element(
903 rejected_roots.begin(), rejected_roots.end(),
905 return qp_solver::ScoreRoot(a) < qp_solver::ScoreRoot(b);
907 return least_bad->omega;
914 Spin spin,
double intercept0,
double frequency0,
Index gw_level,
915 double left_limit,
double right_limit,
bool allow_rejected_return,
918 if (
opt_.qp_grid_search_mode ==
"adaptive") {
920 gw_level, left_limit, right_limit,
921 allow_rejected_return, stats);
924 if (
opt_.qp_grid_search_mode ==
"dense") {
926 left_limit, right_limit,
927 allow_rejected_return, stats);
930 if (
opt_.qp_grid_search_mode ==
"adaptive_with_dense_fallback") {
933 spin, intercept0, frequency0, gw_level, left_limit, right_limit,
934 allow_rejected_return, &total_stats);
936 if (stats !=
nullptr) {
937 *stats = total_stats;
944 spin, intercept0, frequency0, gw_level, left_limit, right_limit,
945 allow_rejected_return, &dense_stats);
946 total_stats.
Add(dense_stats);
952 <<
" Adaptive QP scan failed for "
954 <<
", retrying dense grid scan in [" << left_limit <<
", "
955 << right_limit <<
"]" << std::flush;
959 if (stats !=
nullptr) {
960 *stats = total_stats;
965 throw std::runtime_error(
"Unknown gw.qp_grid_search_mode '" +
966 opt_.qp_grid_search_mode +
"'");
973 boost::optional<double> newf = boost::none;
977 opt_.g_sc_max_iterations,
opt_.g_sc_limit,
opt_.qp_solver_alpha);
979 const double freq_new = newton.
FindRoot(f, frequency0);
984 if (stats !=
nullptr) {
992 double epsilon)
const {
994 const double diff_max = (e1 - e2).cwiseAbs().maxCoeff(&state);
996 <<
" StateNo:" << state << std::flush;
997 return diff_max <= epsilon;
1003 <<
TimeStamp() <<
" WARNING: no off-diagonal Sigma_c for sigma "
1004 <<
"integration " <<
opt_.sigma_integration
1005 <<
"; the DQP Hamiltonian has no off-diagonal correlation"
1009 Eigen::VectorXd diag_backup_beta =
Sigma_c_beta_.diagonal();
1027Eigen::SelfAdjointEigenSolver<Eigen::MatrixXd>
1029 Eigen::SelfAdjointEigenSolver<Eigen::MatrixXd> qpdiag(
getHQPAlpha());
1034Eigen::SelfAdjointEigenSolver<Eigen::MatrixXd>
1036 Eigen::SelfAdjointEigenSolver<Eigen::MatrixXd> qpdiag(
getHQPBeta());
1042 const Eigen::VectorXd gwa =
1049 << (boost::format(
" ====== Perturbative %1% quasiparticle energies "
1050 "(Hartree) ======") %
1055 if (
opt_.qpmin <= homo && homo + 1 <=
opt_.qpmax) {
1056 const double dft_gap = dft(homo + 1) - dft(homo);
1057 const double qp_gap = gwa(homo + 1 -
opt_.qpmin) - gwa(homo -
opt_.qpmin);
1060 << (boost::format(
" %1% DFT gap = %2$+1.6f Hartree %1% GWA gap = "
1061 "%3$+1.6f Hartree Delta = %4$+1.6f Hartree") %
1062 SpinName(spin) % dft_gap % qp_gap % (qp_gap - dft_gap))
1071 << (boost::format(
" = %1$4d (%2%) %3% DFT = %4$+1.4f VXC = %5$+1.4f "
1072 "S-X = %6$+1.4f S-C = %7$+1.4f GWA = %8$+1.4f") %
1075 SigmaC(spin)(i, i) % gwa(i))
1082 const Eigen::VectorXd& qp_diag_energies)
const {
1083 const Eigen::VectorXd gwa =
1090 <<
" quasiparticle Hamiltonian" << std::flush;
1092 if (
opt_.qpmin <= homo && homo + 1 <=
opt_.qpmax) {
1093 const double dft_gap = dft(homo + 1) - dft(homo);
1094 const double pqp_gap = gwa(homo + 1 -
opt_.qpmin) - gwa(homo -
opt_.qpmin);
1095 const double dqp_gap = qp_diag_energies(homo + 1 -
opt_.qpmin) -
1096 qp_diag_energies(homo -
opt_.qpmin);
1099 << (boost::format(
" %1% DFT gap = %2$+1.6f Hartree %1% PQP gap = "
1100 "%3$+1.6f Hartree %1% DQP gap = %4$+1.6f Hartree") %
1101 SpinName(spin) % dft_gap % pqp_gap % dqp_gap)
1110 << (boost::format(
" = %1$4d (%2%) %3% PQP = %4$+1.6f DQP = %5$+1.6f") %
1112 qp_diag_energies(i))
Anderson mixing as convergence acceleration in SCF/fixed point problems.
void UpdateInput(const Eigen::VectorXd &newInput)
const Eigen::VectorXd MixHistory()
void UpdateOutput(const Eigen::VectorXd &newOutput)
void Configure(const Index order, const double alpha)
const QPStats & GetStats() const
double deriv(double frequency) const
double value(double frequency, EvalStage stage=EvalStage::Other) const
boost::optional< double > SolveQP_Grid_Windowed(Spin spin, double intercept0, double frequency0, Index gw_level, double left_limit, double right_limit, bool allow_rejected_return=true, QPStats *stats=nullptr) const
void PrintCompetingRoots(Spin spin, Log::Level level) const
TCMatrix_gwbse_spin & Mmn_
Eigen::SelfAdjointEigenSolver< Eigen::MatrixXd > DiagonalizeQPHamiltonianAlpha() const
bool Converged(const Eigen::VectorXd &e1, const Eigen::VectorXd &e2, double epsilon) const
Eigen::MatrixXd core_exchange_alpha_
void PrintQP_Energies(Spin spin, const Eigen::VectorXd &qp_diag_energies) const
Eigen::MatrixXd & SigmaC(Spin spin)
const Eigen::VectorXd & DftEnergies(Spin spin) const
std::unique_ptr< Sigma_base_UKS > sigma_alpha_
boost::optional< double > SolveQP_Linearisation(Spin spin, double intercept0, double frequency0, Index gw_level, QPStats *stats=nullptr) const
std::string LevelLabel(Spin spin, Index level) const
Eigen::VectorXd tracked_Z_[2]
Eigen::MatrixXd Sigma_x_alpha_
std::unique_ptr< Sigma_base_UKS > sigma_beta_
boost::optional< double > SolveQP_Grid_Windowed_Adaptive(Spin spin, double intercept0, double frequency0, Index gw_level, double left_limit, double right_limit, bool allow_rejected_return=true, QPStats *stats=nullptr) const
boost::optional< double > SolveQP_Grid(Spin spin, double intercept0, double frequency0, Index gw_level, QPStats *stats=nullptr) const
Eigen::MatrixXd Sigma_c_beta_
Eigen::MatrixXd & SigmaX(Spin spin)
Eigen::VectorXd getGWAResultsAlpha() const
const Eigen::MatrixXd & vxc_alpha_
Eigen::VectorXd ScissorShift_DFTlevel(const Eigen::VectorXd &dft_energies, Index homo) const
const Eigen::VectorXd & RPAInputEnergiesAlpha() const
Index tracked_local_total_
qp_solver::WindowDiagnostics QPWindowDiagnostics
const char * OccupationTag(Spin spin, Index level) const
Eigen::MatrixXd core_exchange_beta_
Sigma_base_UKS & SigmaEvaluator(Spin spin)
Eigen::VectorXd SolveQP(Spin spin, const Eigen::VectorXd &frequencies) const
const Eigen::VectorXd & RPAInputEnergiesBeta() const
Eigen::MatrixXd getHQPBeta() const
void PrintGWA_Energies(Spin spin) const
Eigen::VectorXd tracked_change_[2]
Eigen::VectorXd getGWAResultsBeta() const
Eigen::MatrixXd getHQPAlpha() const
Eigen::MatrixXd Sigma_x_beta_
const char * SpinName(Spin spin) const
GW_UKS(Logger &log, TCMatrix_gwbse_spin &Mmn, const Eigen::MatrixXd &vxc_alpha, const Eigen::MatrixXd &vxc_beta, const Eigen::VectorXd &dft_energies_alpha, const Eigen::VectorXd &dft_energies_beta)
const Eigen::VectorXd & dft_energies_alpha_
double CalcSpinHomoLumoShift(const Eigen::VectorXd &frequencies, Spin spin) const
boost::optional< double > SolveQP_Grid_Windowed_Dense(Spin spin, double intercept0, double frequency0, Index gw_level, double left_limit, double right_limit, bool allow_rejected_return=true, QPStats *stats=nullptr) const
const Eigen::MatrixXd & vxc_beta_
const Eigen::VectorXd & dft_energies_beta_
qp_solver::RootCandidate QPRootCandidate
Eigen::SelfAdjointEigenSolver< Eigen::MatrixXd > DiagonalizeQPHamiltonianBeta() const
Eigen::MatrixXd Sigma_c_alpha_
const Eigen::MatrixXd & Vxc(Spin spin) const
std::vector< qp_solver::CompetingRoots > competing_roots_[2]
void configure(const options &opt)
void RecordCompetingRoots(Spin spin, Index gw_level, const std::vector< QPRootCandidate > &roots, double chosen) const
void CalculateGWPerturbation()
boost::optional< double > SolveQP_FixedPoint(Spin spin, double intercept0, double frequency0, Index gw_level, QPStats *stats=nullptr) const
Index Homo(Spin spin) const
Eigen::VectorXd tracked_root_[2]
std::string CreateIndexString(const std::vector< Index > &indeces) const
Logger is used for thread-safe output of messages.
static std::string Usage()
Newton Rapson rootfinder for 1d functions.
double FindRoot(const Func &f, double x0)
When evGW rebuilds the screening W.
void Built(const Eigen::VectorXd &energies)
W has just been built from these energies.
void Configure(Mode mode, double ratio, Index max_inner)
static std::string Name(Mode mode)
Next Decide(double residual, const Eigen::VectorXd &new_energies, double limit, double *drift_out=nullptr)
static Mode Parse(const std::string &name)
Index inner() const
QP iterations since W was last built (before the current one).
void SetSharedPPM(const PPM &ppm)
Timestamp returns the current time as a string Example: cout << TimeStamp().
#define XTP_LOG(level, log)
boost::optional< RootCandidate > SolveQP_Tracked(QPFunc &fqp, double center, double halfwidth, double Z_previous, double min_Z_fraction, const SolverOptions &opt, bool use_brent=false)
boost::optional< double > SolveQP_Grid_Windowed(QPFunc &fqp, double frequency0, double left_limit, double right_limit, Index gw_sc_iteration, const SolverOptions &opt, WindowDiagnostics *wdiag=nullptr, std::vector< RootCandidate > *accepted_roots_out=nullptr, std::vector< RootCandidate > *rejected_roots_out=nullptr, bool use_brent=false)
std::string LargestResiduals(const Eigen::VectorXd &solution, const Eigen::VectorXd &input, Index first_level, Index n=5)
void NormalizeGridSearchOptions(Opt &opt)
boost::optional< double > LinearisedRoot(double w0, double f0, double fprime)
const RootCandidate & SelectRoot(const std::vector< RootCandidate > &roots, const SolverOptions &opt)
boost::optional< RootCandidate > RefineQPInterval(double lowerbound, double f_lowerbound, double upperbound, double f_upperbound, const QPFunc &f, double reference, const SolverOptions &opt, bool use_brent)
Charge transport classes.
Provides a means for comparing floating point numbers.
static Level current_level
std::string quadrature_scheme
double qp_adaptive_shell_width
Index qp_adaptive_shell_count
double qp_full_window_half_width
Index qp_bisection_max_iter
std::size_t sigma_repeat_calls
std::size_t sigma_scan_calls
void Add(const Stats &other)
std::size_t TotalSigmaCalls() const
std::size_t sigma_refine_calls
std::size_t sigma_other_calls
std::size_t sigma_unique_frequencies
Index first_interval_shell
Index first_accepted_shell