44 const Eigen::MatrixXd& Hqp_in) {
53 if (
opt_.use_Hqp_offdiag) {
62 const options& opt,
const Eigen::VectorXd& RPAInputEnergies,
63 const Eigen::MatrixXd& Hqp_in,
const Eigen::VectorXd& epsilon_0_inv) {
72 if (
opt_.use_Hqp_offdiag) {
87 throw std::runtime_error(
88 "Unsupported QMStateType in BSE::GetBSEEigenSystem");
99 throw std::runtime_error(
100 "Unsupported QMStateType in BSE::GetBSEEigenSystem");
106 return " ====== singlet energies (eV) ====== ";
108 return " ====== triplet energies (eV) ====== ";
110 throw std::runtime_error(
111 "Unsupported QMStateType in BSE::StateEnergiesHeader");
121 throw std::runtime_error(
"Unsupported QMStateType in BSE::StateShortLabel");
131 throw std::runtime_error(
132 "Unsupported QMStateType in BSE::StateDynamicLabel");
142 throw std::runtime_error(
143 "Unsupported QMStateType in BSE::ExchangePrefactor");
148 const Eigen::VectorXd& RPAInputEnergies) {
153 Eigen::MatrixXd Hqp_BSE = Eigen::MatrixXd::Zero(hqp_size, hqp_size);
158 Hqp_BSE = Hqp.block(start, start, hqp_size, hqp_size);
160 Index virtoffset = gwsize - start;
161 Hqp_BSE.topLeftCorner(virtoffset, virtoffset) =
162 Hqp.block(start, start, virtoffset, virtoffset);
165 Hqp_BSE.diagonal().tail(virt_extra) =
166 RPAInputEnergies.segment(RPAoffset + virtoffset, virt_extra);
172 Hqp_BSE.diagonal().head(occ_extra) =
173 RPAInputEnergies.segment(RPAoffset, occ_extra);
175 Hqp_BSE.block(occ_extra, occ_extra, gwsize, gwsize) = Hqp;
178 Index virtoffset = occ_extra + gwsize;
180 Hqp_BSE.diagonal().tail(virt_extra) =
181 RPAInputEnergies.segment(RPAoffset + virtoffset, virt_extra);
189 const Eigen::VectorXd& RPAInputEnergies,
double energy) {
194 Eigen::SelfAdjointEigenSolver<Eigen::MatrixXd> es(
196 Mmn_.MultiplyRightWithAuxMatrix(es.eigenvectors());
199 for (
Index i = 0; i < es.eigenvalues().size(); ++i) {
200 if (es.eigenvalues()(i) > 1
e-8) {
206template <
typename BSE_OPERATOR>
248 <<
TimeStamp() <<
" Setup TDA singlet hamiltonian " << flush;
266template <
typename BSE_OPERATOR>
269 std::chrono::time_point<std::chrono::system_clock> start =
270 std::chrono::system_clock::now();
285 std::chrono::time_point<std::chrono::system_clock> end =
286 std::chrono::system_clock::now();
287 std::chrono::duration<double> elapsed_time = end - start;
290 << elapsed_time.count() <<
" secs" << flush;
301 <<
TimeStamp() <<
" Setup Full singlet hamiltonian " << flush;
311 <<
TimeStamp() <<
" Setup Full triplet hamiltonian " << flush;
315template <
typename BSE_OPERATOR_A,
typename BSE_OPERATOR_B>
317 BSE_OPERATOR_B& Bop)
const {
318 std::chrono::time_point<std::chrono::system_clock> start =
319 std::chrono::system_clock::now();
333 Aop.diagonal(), Bop.diagonal(),
opt_.nmax);
340 Eigen::MatrixXd tmpX = DS.
eigenvectors().topRows(Aop.rows());
341 Eigen::MatrixXd tmpY = DS.
eigenvectors().bottomRows(Bop.rows());
344 Eigen::VectorXd normX = tmpX.colwise().squaredNorm();
345 Eigen::VectorXd normY = tmpY.colwise().squaredNorm();
347 Eigen::ArrayXd sqinvnorm = (normX - normY).array().inverse().cwiseSqrt();
349 result.
eigenvectors() = tmpX * sqinvnorm.matrix().asDiagonal();
350 result.
eigenvectors2() = tmpY * sqinvnorm.matrix().asDiagonal();
352 std::chrono::time_point<std::chrono::system_clock> end =
353 std::chrono::system_clock::now();
354 std::chrono::duration<double> elapsed_time = end - start;
357 << elapsed_time.count() <<
" secs" << flush;
365 double dq = frag.value().H[state] + frag.value().E[state];
366 double qeff = dq + frag.value().Gs;
369 " Fragment %1$4d -- hole: %2$5.1f%% electron: "
370 "%3$5.1f%% dQ: %4$+5.2f Qeff: %5$+5.2f") %
371 int(frag.getId()) % (100.0 * frag.value().
H[state]) %
372 (-100.0 * frag.value().E[state]) % dq % qeff
381 double weight = weights(i_bse);
382 if (weight >
opt_.min_print_weight) {
385 " HOMO-%1$-3d -> LUMO+%2$-3d : %3$3.1f%%") %
386 (
opt_.homo - vc.
v(i_bse)) % (vc.
c(i_bse) -
opt_.homo - 1) %
402 if (fragments.size() > 0) {
408 const Eigen::VectorXd& energies = bse.
eigenvalues();
413 Eigen::VectorXd weights = bse.
eigenvectors().col(i).cwiseAbs2();
418 double osc = oscs[i];
421 " %1$2s = %2$4d Omega = %3$+1.12f eV lamdba = %4$+3.2f nm "
422 "<FT> = %5$+1.4f <K_x> = %6$+1.4f <K_d> = %7$+1.4f") %
424 (1240.0 / (hrt2ev * energies(i))) %
433 " TrDipole length gauge[e*bohr] dx = %1$+1.4f dy = "
434 "%2$+1.4f dz = %3$+1.4f |d|^2 = %4$+1.4f f = %5$+1.4f") %
435 trdip[0] % trdip[1] % trdip[2] % (trdip.squaredNorm()) % osc
439 if (fragments.size() > 0) {
454 if (fragments.size() > 0) {
460 const Eigen::VectorXd& energies = bse.
eigenvalues();
464 Eigen::VectorXd weights = bse.
eigenvectors().col(i).cwiseAbs2();
471 " %1$2s = %2$4d Omega = %3$+1.12f eV lamdba = %4$+3.2f nm "
472 "<FT> = %5$+1.4f <K_d> = %6$+1.4f") %
481 if (fragments.size() > 0) {
491Eigen::VectorXd
ExpValue(
const Eigen::MatrixXd& state1, OP OPxstate2) {
492 return state1.cwiseProduct(OPxstate2.eval()).colwise().sum().transpose();
495Eigen::VectorXd
ExpValue(
const Eigen::MatrixXd& state1,
496 const Eigen::MatrixXd& OPxstate2) {
497 return state1.cwiseProduct(OPxstate2).colwise().sum().transpose();
500template <
typename BSE_OPERATOR>
517 expectation_values.
cross_term = Eigen::VectorXd::Zero(0);
519 return expectation_values;
522template <
typename BSE_OPERATOR>
530 const Eigen::MatrixXd BSECoefs_state =
533 const Eigen::MatrixXd temp =
H * BSECoefs_state;
538 const Eigen::MatrixXd BSECoefs2_state =
542 ExpValue(BSECoefs2_state,
H * BSECoefs2_state);
545 expectation_values.
cross_term = Eigen::VectorXd::Zero(0);
548 return expectation_values;
623 Eigen::VectorXd Hd_static_contribution = expectation_values.
direct_term;
628 Hd_static_contribution += expectation_values.
cross_term;
631 const Eigen::VectorXd& BSEenergies = BSECoefs.
eigenvalues();
634 Eigen::VectorXd BSEenergies_dynamic = BSEenergies;
637 for (
Index i_exc = 0; i_exc < BSEenergies.size(); i_exc++) {
639 <<
" static " << BSEenergies(i_exc) << flush;
644 double old_energy = BSEenergies_dynamic(i_exc);
650 QMState state(type, i_exc,
false);
652 Eigen::VectorXd Hd_dynamic_contribution = expectation_values.
direct_term;
658 Hd_dynamic_contribution += expectation_values.
cross_term;
662 BSEenergies_dynamic(i_exc) = BSEenergies(i_exc) +
663 Hd_static_contribution(i_exc) -
664 Hd_dynamic_contribution(0);
667 <<
"Dynamical Screening BSE, excitation " << i_exc <<
" iteration "
668 << iter <<
" dynamic " << BSEenergies_dynamic(i_exc) << flush;
671 if (std::abs(BSEenergies_dynamic(i_exc) - old_energy) <
dyn_tolerance_) {
682 "dynamical screening (eV) ====== "
686 double osc = oscs[i];
689 " S(dynamic) = %1$4d Omega = %2$+1.12f eV lamdba = %3$+3.2f "
691 (i + 1) % (hrt2ev * BSEenergies_dynamic(i)) %
692 (1240.0 / (hrt2ev * BSEenergies_dynamic(i))) %
693 (osc * BSEenergies_dynamic(i) / BSEenergies(i))
700 "dynamical screening (eV) ====== "
705 " T(dynamic) = %1$4d Omega = %2$+1.12f eV lamdba = %3$+3.2f "
707 (i + 1) % (hrt2ev * BSEenergies_dynamic(i)) %
708 (1240.0 / (hrt2ev * BSEenergies_dynamic(i)))
713 throw std::runtime_error(
714 "Unsupported QMStateType in BSE::Perturbative_DynamicalScreening");
void Solve_singlets(Orbitals &orb) const
void printFragInfo(const std::vector< QMFragment< BSE_Population > > &frags, Index state) const
void PrintWeights(const Eigen::VectorXd &weights) const
std::string StateDynamicLabel(const QMStateType &type) const
void configure_with_precomputed_screening(const options &opt, const Eigen::VectorXd &RPAEnergies, const Eigen::MatrixXd &Hqp_in, const Eigen::VectorXd &epsilon_0_inv)
void Analyze_singlets(std::vector< QMFragment< BSE_Population > > fragments, const Orbitals &orb) const
tools::EigenSystem Solve_triplets_BTDA() const
TripletOperator_TDA getTripletOperator_TDA() const
SingletOperator_TDA getSingletOperator_TDA() const
ExpectationValues ExpectationValue_Operator_State(const QMState &state, const Orbitals &orb, const BSE_OPERATOR &H) const
tools::EigenSystem Solve_singlets_BTDA() const
void Perturbative_DynamicalScreening(const QMStateType &type, Orbitals &orb)
void Analyze_triplets(std::vector< QMFragment< BSE_Population > > fragments, const Orbitals &orb) const
void SetupDirectInteractionOperator(const Eigen::VectorXd &DFTenergies, double energy)
void configure(const options &opt, const Eigen::VectorXd &RPAEnergies, const Eigen::MatrixXd &Hqp_in)
tools::EigenSystem & GetBSEEigenSystem(const QMStateType &type, Orbitals &orb) const
Eigen::VectorXd epsilon_0_inv_
ExpectationValues ExpectationValue_Operator(const QMStateType &type, const Orbitals &orb, const BSE_OPERATOR &H) const
Interaction Analyze_eh_interaction(const QMStateType &type, const Orbitals &orb) const
double ExchangePrefactor(const QMStateType &type) const
tools::EigenSystem Solve_singlets_TDA() const
void configureBSEOperator(BSE_OPERATOR &H) const
tools::EigenSystem solve_hermitian(BSE_OPERATOR &h) const
void Solve_triplets(Orbitals &orb) const
tools::EigenSystem Solve_nonhermitian_Davidson(BSE_OPERATOR_A &Aop, BSE_OPERATOR_B &Bop) const
Eigen::MatrixXd AdjustHqpSize(const Eigen::MatrixXd &Hqp_in, const Eigen::VectorXd &RPAInputEnergies)
std::string StateShortLabel(const QMStateType &type) const
tools::EigenSystem Solve_triplets_TDA() const
std::string StateEnergiesHeader(const QMStateType &type) const
Use Davidson algorithm to solve A*V=E*V.
void set_max_search_space(Index N)
Eigen::VectorXd eigenvalues() const
void solve(const MatrixReplacement &A, Index neigen, Index size_initial_guess=0)
void set_iter_max(Index N)
void set_matrix_type(std::string mt)
void set_correction(std::string method)
void set_size_update(std::string update_size)
void set_tolerance(std::string tol)
Eigen::MatrixXd eigenvectors() const
Container for molecular orbitals and derived one-particle data.
const tools::EigenSystem & BSETriplets() const
Return read-only access to triplet BSE eigenpairs.
void CalcCoupledTransition_Dipoles()
const tools::EigenSystem & BSESinglets() const
Return read-only access to singlet BSE eigenpairs.
bool getTDAApprox() const
Return whether the Tamm-Dancoff approximation is enabled.
Eigen::VectorXd Oscillatorstrengths() const
const std::vector< Eigen::Vector3d > & TransitionDipoles() const
Return the stored transition dipole moments.
const Eigen::VectorXd & RPAInputEnergies() const
Return read-only access to the RPA input energies.
const Eigen::VectorXd & BSETriplets_dynamic() const
Return dynamically screened triplet BSE energies.
void setTDAApprox(bool usedTDA)
Enable or disable the Tamm-Dancoff approximation flag.
const Eigen::VectorXd & BSESinglets_dynamic() const
Return dynamically screened singlet BSE energies.
void CalcChargeperFragment(std::vector< QMFragment< BSE_Population > > &frags, const Orbitals &orbitals, QMStateType type) const
Identifier for QMstates. Strings like S1 are converted into enum +zero indexed int.
const QMStateType & Type() const
void setRPAInputEnergies(const Eigen::VectorXd &rpaenergies)
Eigen::MatrixXd calculate_epsilon_r(double frequency) const
void configure(Index homo, Index rpamin, Index rpamax)
Timestamp returns the current time as a string Example: cout << TimeStamp()
This class transforms a pair of indices v,c into a compound index I, via I=ctotal*v+c the fast dimens...
Index c(Index index) const
Index v(Index index) const
#define XTP_LOG(level, log)
Charge transport classes.
Eigen::VectorXd ExpValue(const Eigen::MatrixXd &state1, OP OPxstate2)
BSE_OPERATOR< 1, 0, 0, 0 > HqpOperator
BSE_OPERATOR< 0, 0, 1, 0 > HdOperator
BSE_OPERATOR< 0, 0, 0, 1 > Hd2Operator
BSE_OPERATOR< 1, 2, 1, 0 > SingletOperator_TDA
Populationanalysis< true > Lowdin
Eigen::MatrixXd BuildFullBSEXRankedInitialGuess(const Eigen::VectorXd &adiag, const Eigen::VectorXd &bdiag, Index nroots)
Build an initial guess for full-BSE Davidson diagonalization.
BSE_OPERATOR< 1, 0, 1, 0 > TripletOperator_TDA
BSE_OPERATOR< 0, 2, 0, 1 > SingletOperator_BTDA_B
BSE_OPERATOR< 0, 1, 0, 0 > HxOperator
Provides a means for comparing floating point numbers.
Eigen::VectorXd direct_term
Eigen::VectorXd cross_term
Eigen::VectorXd qp_contrib
Eigen::VectorXd exchange_contrib
Eigen::VectorXd direct_contrib