23#include <boost/algorithm/string.hpp>
24#include <boost/format.hpp>
46 Index ignored_corelevels = 0;
49 basis.
Load(
"corelevels");
50 Index coreElectrons = 0;
51 for (
const auto& atom :
orbitals_.QMAtoms()) {
54 ignored_corelevels = coreElectrons / 2;
56 return ignored_corelevels;
73 std::string ranges = options.
get(
".ranges").
as<std::string>();
77 if (ranges ==
"factor") {
79 double rpamaxfactor = options.
get(
".rpamax").
as<
double>();
80 rpamax =
Index(rpamaxfactor *
double(num_of_levels)) -
83 double qpminfactor = options.
get(
".qpmin").
as<
double>();
85 num_of_occlevels -
Index(qpminfactor *
double(num_of_occlevels)) - 1;
87 double qpmaxfactor = options.
get(
".qpmax").
as<
double>();
89 num_of_occlevels +
Index(qpmaxfactor *
double(num_of_occlevels)) - 1;
91 double bseminfactor = options.
get(
".bsemin").
as<
double>();
93 num_of_occlevels -
Index(bseminfactor *
double(num_of_occlevels)) - 1;
95 double bsemaxfactor = options.
get(
".bsemax").
as<
double>();
97 num_of_occlevels +
Index(bsemaxfactor *
double(num_of_occlevels)) - 1;
99 }
else if (ranges ==
"explicit") {
104 bse_vmin = options.
get(
".bsemin").
as<
Index>();
105 bse_cmax = options.
get(
".bsemax").
as<
Index>();
106 }
else if (ranges ==
"default") {
107 rpamax = num_of_levels - 1;
109 qpmax = 3 * homo + 1;
111 bse_cmax = 3 * homo + 1;
112 }
else if (ranges ==
"full") {
113 rpamax = num_of_levels - 1;
115 qpmax = num_of_levels - 1;
117 bse_cmax = num_of_levels - 1;
119 std::string ignore_corelevels =
120 options.
get(
".ignore_corelevels").
as<std::string>();
122 if (ignore_corelevels ==
"RPA" || ignore_corelevels ==
"GW" ||
123 ignore_corelevels ==
"BSE") {
125 if (ignore_corelevels ==
"RPA") {
126 rpamin = ignored_corelevels;
128 if (ignore_corelevels ==
"GW" || ignore_corelevels ==
"RPA") {
129 if (qpmin < ignored_corelevels) {
130 qpmin = ignored_corelevels;
133 if (ignore_corelevels ==
"GW" || ignore_corelevels ==
"RPA" ||
134 ignore_corelevels ==
"BSE") {
135 if (bse_vmin < ignored_corelevels) {
136 bse_vmin = ignored_corelevels;
141 <<
TimeStamp() <<
" Ignoring " << ignored_corelevels
142 <<
" core levels for " << ignore_corelevels <<
" and beyond." << flush;
146 if (rpamax > num_of_levels) {
147 rpamax = num_of_levels - 1;
149 if (qpmax > num_of_levels) {
150 qpmax = num_of_levels - 1;
152 if (bse_cmax > num_of_levels) {
153 bse_cmax = num_of_levels - 1;
178 orbitals_.setBSEindices(bse_vmin, bse_cmax);
181 Index bse_vmax = homo;
182 Index bse_cmin = homo + 1;
183 Index bse_vtotal = bse_vmax - bse_vmin + 1;
184 Index bse_ctotal = bse_cmax - bse_cmin + 1;
185 Index bse_size = bse_vtotal * bse_ctotal;
188 <<
":" << rpamax <<
"]" << flush;
190 <<
":" << qpmax <<
"]" << flush;
192 <<
TimeStamp() <<
" BSE level range occ[" << bse_vmin <<
":" << bse_vmax
193 <<
"] virt[" << bse_cmin <<
":" << bse_cmax <<
"]" << flush;
203 options.
get(
"bse.davidson.correction").
as<std::string>();
206 options.
get(
"bse.davidson.tolerance").
as<std::string>();
209 options.
get(
"bse.davidson.update").
as<std::string>();
221 Index full_bse_size = (
bseopt_.useTDA) ? bse_size : 2 * bse_size;
223 << full_bse_size <<
"x" << full_bse_size << flush;
225 bseopt_.use_Hqp_offdiag = options.
get(
"bse.use_Hqp_offdiag").
as<
bool>();
227 if (!
bseopt_.use_Hqp_offdiag) {
229 <<
" BSE without Hqp offdiagonal elements" << flush;
232 <<
" BSE with Hqp offdiagonal elements" << flush;
236 bseopt_.dyn_tolerance = options.
get(
"bse.dyn_screen_tol").
as<
double>();
237 if (
bseopt_.max_dyn_iter > 0) {
247 }
else if (options.
exists(
".auxbasisset")) {
254 }
catch (std::runtime_error&) {
256 "There is no auxbasis from the dftcalculation nor did you specify an "
257 "auxbasisset for the gwbse calculation. Also no auxiliary basisset "
262 <<
" Could not find an auxbasisset using " <<
auxbasis_name_ << flush;
265 std::string mode = options.
get(
"gw.mode").
as<std::string>();
266 if (mode ==
"G0W0") {
267 gwopt_.gw_sc_max_iterations = 1;
268 }
else if (mode ==
"evGW") {
276 gwopt_.shift = options.
get(
"gw.scissor_shift").
as<
double>();
278 options.
get(
"gw.qp_sc_limit").
as<
double>();
281 gwopt_.g_sc_max_iterations =
287 if (mode ==
"evGW") {
292 options.
get(
"gw.sc_limit").
as<
double>();
295 <<
" qp_sc_limit [Hartree]: " <<
gwopt_.g_sc_limit << flush;
296 if (
gwopt_.gw_sc_max_iterations > 1) {
298 <<
" gw_sc_limit [Hartree]: " <<
gwopt_.gw_sc_limit << flush;
300 bseopt_.min_print_weight = options.
get(
"bse.print_weight").
as<
double>();
304 std::string tasks_string = options.
get(
".tasks").
as<std::string>();
305 boost::algorithm::to_lower(tasks_string);
306 if (tasks_string.find(
"all") != std::string::npos) {
311 if (tasks_string.find(
"gw") != std::string::npos) {
314 if (tasks_string.find(
"singlets") != std::string::npos) {
317 if (tasks_string.find(
"triplets") != std::string::npos) {
336 if (options.
exists(
"bse.fragments")) {
337 std::vector<tools::Property*> prop_region =
338 options.
Select(
"bse.fragments.fragment");
341 std::string indices = prop->get(
"indices").as<std::string>();
347 gwopt_.sigma_integration =
348 options.
get(
"gw.sigma_integrator").
as<std::string>();
350 <<
" Sigma integration: " <<
gwopt_.sigma_integration << flush;
353 if (
gwopt_.sigma_integration ==
"exact") {
355 <<
" RPA Hamiltonian size: " << (homo + 1 - rpamin) * (rpamax - homo)
358 if (
gwopt_.sigma_integration ==
"cda") {
361 <<
" Quadrature integration order : " <<
gwopt_.order << flush;
362 gwopt_.quadrature_scheme =
363 options.
get(
"gw.quadrature_scheme").
as<std::string>();
365 <<
" Quadrature integration scheme : " <<
gwopt_.quadrature_scheme
367 gwopt_.alpha = options.
get(
"gw.alpha").
as<
double>();
369 <<
" Alpha smoothing parameter : " <<
gwopt_.alpha << flush;
371 gwopt_.qp_solver = options.
get(
"gw.qp_solver").
as<std::string>();
374 if (
gwopt_.qp_solver ==
"grid") {
376 gwopt_.qp_grid_spacing = options.
get(
"gw.qp_grid_spacing").
as<
double>();
378 <<
" QP grid steps: " <<
gwopt_.qp_grid_steps << flush;
380 <<
" QP grid spacing: " <<
gwopt_.qp_grid_spacing << flush;
388 gwopt_.gw_mixing_alpha = options.
get(
"gw.mixing_alpha").
as<
double>();
390 if (mode ==
"evGW") {
391 if (
gwopt_.gw_mixing_order == 0) {
393 }
else if (
gwopt_.gw_mixing_order == 1) {
395 <<
gwopt_.gw_mixing_alpha << std::flush;
398 <<
gwopt_.gw_mixing_order <<
" using alpha "
399 <<
gwopt_.gw_mixing_alpha << std::flush;
403 if (options.
exists(
"gw.sigma_plot")) {
408 options.
get(
"gw.sigma_plot.filename").
as<std::string>();
429 (boost::format(
"%1$+1.6f ") % (
orbitals_.getDFTTotalEnergy() * hrt2ev)).str());
440 (boost::format(
"%1$+1.6f ") %
445 (boost::format(
"%1$+1.6f ") % (
orbitals_.QPpertEnergies()(state) * hrt2ev))
448 level_summary.
add(
"qp_energy",
449 (boost::format(
"%1$+1.6f ") %
450 (
orbitals_.QPdiag().eigenvalues()(state) * hrt2ev))
460 "omega", (boost::format(
"%1$+1.6f ") %
461 (
orbitals_.BSESinglets().eigenvalues()(state) * hrt2ev))
465 const Eigen::Vector3d& dipoles = (
orbitals_.TransitionDipoles())[state];
466 double f = 2 * dipoles.squaredNorm() *
467 orbitals_.BSESinglets().eigenvalues()(state) / 3.0;
469 level_summary.
add(
"f", (boost::format(
"%1$+1.6f ") % f).str());
471 "Trdipole", (boost::format(
"%1$+1.4f %2$+1.4f %3$+1.4f") % dipoles.x() %
472 dipoles.y() % dipoles.z())
485 "omega", (boost::format(
"%1$+1.6f ") %
486 (
orbitals_.BSETriplets().eigenvalues()(state) * hrt2ev))
504 if (
orbitals_.getXCFunctionalName().empty()) {
508 throw std::runtime_error(
"Functionals from DFT " +
509 orbitals_.getXCFunctionalName() +
" GWBSE " +
517 <<
TimeStamp() <<
" Setup grid for integration with gridsize: " <<
grid_
518 <<
" with " << grid.
getGridSize() <<
" points, divided into "
525 Eigen::MatrixXd DMAT =
orbitals_.DensityMatrixGroundState();
532 Eigen::MatrixXd mos =
535 Eigen::MatrixXd vxc = mos.transpose() * e_vxc_ao.
matrix() * mos;
537 <<
TimeStamp() <<
" Calculated exchange-correlation expectation values "
551 <<
TimeStamp() <<
" Using MKL overload for Eigen " << flush;
555 <<
" Using native Eigen implementation, no BLAS overload " << flush;
560 <<
TimeStamp() <<
" Using CUDA support for tensor multiplication with "
561 << nogpus <<
" GPUs." << flush;
565 <<
TimeStamp() <<
" Molecule Coordinates [A] " << flush;
567 std::string output = (boost::format(
"%5d"
569 " %1.4f %1.4f %1.4f") %
570 atom.getId() % atom.getElement() %
579 std::string dft_package =
orbitals_.getQMpackage();
581 <<
TimeStamp() <<
" DFT data was created by " << dft_package << flush;
603 <<
" size:" << frag.size() << flush;
608 throw std::runtime_error(
609 "You want no GW calculation but the orb file has no QPcoefficients for "
619 <<
" Calculating Mmn_beta (3-center-repulsion x orbitals) " << flush;
620 Mmn.
Fill(auxbasis, dftbasis,
orbitals_.MOs().eigenvectors());
623 <<
" functions from Aux Coulomb matrix to avoid near linear dependencies"
626 <<
TimeStamp() <<
" Calculated Mmn_beta (3-center-repulsion x orbitals) "
632 std::chrono::time_point<std::chrono::system_clock> start =
633 std::chrono::system_clock::now();
651 <<
TimeStamp() <<
" Calculating offdiagonal part of Sigma " << flush;
654 <<
TimeStamp() <<
" Calculated offdiagonal part of Sigma " << flush;
658 Eigen::SelfAdjointEigenSolver<Eigen::MatrixXd> es =
660 if (es.info() == Eigen::ComputationInfo::Success) {
662 <<
TimeStamp() <<
" Diagonalized QP Hamiltonian " << flush;
665 orbitals_.QPdiag().eigenvectors() = es.eigenvectors();
666 orbitals_.QPdiag().eigenvalues() = es.eigenvalues();
667 std::chrono::duration<double> elapsed_time =
668 std::chrono::system_clock::now() - start;
670 << elapsed_time.count() <<
" seconds." << flush;
677 throw std::runtime_error(
678 "The ranges for GW and RPA do not agree with the ranges from the "
679 ".orb file, rerun your GW calculation");
681 const Eigen::MatrixXd& qpcoeff =
orbitals_.QPdiag().eigenvectors();
683 Hqp = qpcoeff *
orbitals_.QPdiag().eigenvalues().asDiagonal() *
690 std::chrono::time_point<std::chrono::system_clock> start =
691 std::chrono::system_clock::now();
697 Eigen::VectorXd Hd_static_contrib_triplet;
698 Eigen::VectorXd Hd_static_contrib_singlet;
703 <<
TimeStamp() <<
" Solved BSE for triplets " << flush;
710 <<
TimeStamp() <<
" Solved BSE for singlets " << flush;
728 std::chrono::duration<double> elapsed_time =
729 std::chrono::system_clock::now() - start;
731 << elapsed_time.count() <<
" seconds." << flush;
734 <<
TimeStamp() <<
" GWBSE calculation finished " << flush;
Container to hold Basisfunctions for all atoms.
Index AOBasisSize() const
void Solve_singlets(Orbitals &orb) const
void Analyze_singlets(std::vector< QMFragment< BSE_Population > > fragments, const Orbitals &orb) const
void Perturbative_DynamicalScreening(const QMStateType &type, Orbitals &orb)
void Analyze_triplets(std::vector< QMFragment< BSE_Population > > fragments, const Orbitals &orb) const
void configure(const options &opt, const Eigen::VectorXd &RPAEnergies, const Eigen::MatrixXd &Hqp_in)
void Solve_triplets(Orbitals &orb) const
void Load(const std::string &name)
void Load(const std::string &name)
const ECPElement & getElement(std::string element_type) const
std::vector< QMFragment< BSE_Population > > fragments_
std::string sigma_plot_states_
void addoutput(tools::Property &summary)
std::string auxbasis_name_
Eigen::MatrixXd CalculateVXC(const AOBasis &dftbasis)
std::string dftbasis_name_
void Initialize(tools::Property &options)
double sigma_plot_spacing_
std::string sigma_plot_filename_
bool do_dynamical_screening_bse_
void PlotSigma(std::string filename, Index steps, double spacing, std::string states) const
Eigen::SelfAdjointEigenSolver< Eigen::MatrixXd > DiagonalizeQPHamiltonian() const
void configure(const options &opt)
Eigen::MatrixXd getHQP() const
Eigen::VectorXd getGWAResults() const
Eigen::VectorXd RPAInputEnergies() const
void CalculateGWPerturbation()
Eigen::MatrixXd & matrix()
void Fill(const AOBasis &auxbasis, const AOBasis &dftbasis, const Eigen::MatrixXd &dft_orbitals)
void Initialize(Index basissize, Index mmin, Index mmax, Index nmin, Index nmax)
Index Removedfunctions() const
Timestamp returns the current time as a string Example: cout << TimeStamp()
Index getGridSize() const
void GridSetup(const std::string &type, const QMMolecule &atoms, const AOBasis &basis)
Index getBoxesSize() const
Mat_p_Energy IntegrateVXC(const Eigen::MatrixXd &density_matrix) const
void setXCfunctional(const std::string &functional)
#define XTP_LOG(level, log)
Charge transport classes.
bool XTP_HAS_MKL_OVERLOAD()
Provides a means for comparing floating point numbers.