votca 2026-dev
Loading...
Searching...
No Matches
bse.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// Standard includes
21#include <chrono>
22#include <iostream>
23
24// VOTCA includes
25#include <votca/tools/linalg.h>
26
27// Local VOTCA includes
28#include "votca/xtp/bse.h"
35#include "votca/xtp/rpa.h"
36#include "votca/xtp/vc2index.h"
37
38using std::flush;
39
40namespace votca {
41namespace xtp {
42
43void BSE::configure(const options& opt, const Eigen::VectorXd& RPAInputEnergies,
44 const Eigen::MatrixXd& Hqp_in) {
45 opt_ = opt;
46 bse_vmax_ = opt_.homo;
47 bse_cmin_ = opt_.homo + 1;
48 bse_vtotal_ = bse_vmax_ - opt_.vmin + 1;
49 bse_ctotal_ = opt_.cmax - bse_cmin_ + 1;
51 max_dyn_iter_ = opt_.max_dyn_iter;
52 dyn_tolerance_ = opt_.dyn_tolerance;
53 if (opt_.use_Hqp_offdiag) {
54 Hqp_ = AdjustHqpSize(Hqp_in, RPAInputEnergies);
55 } else {
56 Hqp_ = AdjustHqpSize(Hqp_in, RPAInputEnergies).diagonal().asDiagonal();
57 }
58 SetupDirectInteractionOperator(RPAInputEnergies, 0.0);
59}
60
62 const options& opt, const Eigen::VectorXd& RPAInputEnergies,
63 const Eigen::MatrixXd& Hqp_in, const Eigen::VectorXd& epsilon_0_inv) {
64 opt_ = opt;
65 bse_vmax_ = opt_.homo;
66 bse_cmin_ = opt_.homo + 1;
67 bse_vtotal_ = bse_vmax_ - opt_.vmin + 1;
68 bse_ctotal_ = opt_.cmax - bse_cmin_ + 1;
70 max_dyn_iter_ = opt_.max_dyn_iter;
71 dyn_tolerance_ = opt_.dyn_tolerance;
72 if (opt_.use_Hqp_offdiag) {
73 Hqp_ = AdjustHqpSize(Hqp_in, RPAInputEnergies);
74 } else {
75 Hqp_ = AdjustHqpSize(Hqp_in, RPAInputEnergies).diagonal().asDiagonal();
76 }
77 epsilon_0_inv_ = epsilon_0_inv;
78}
79
81 Orbitals& orb) const {
82 if (type == QMStateType::Singlet) {
83 return orb.BSESinglets();
84 } else if (type == QMStateType::Triplet) {
85 return orb.BSETriplets();
86 } else {
87 throw std::runtime_error(
88 "Unsupported QMStateType in BSE::GetBSEEigenSystem");
89 }
90}
91
93 const Orbitals& orb) const {
94 if (type == QMStateType::Singlet) {
95 return orb.BSESinglets();
96 } else if (type == QMStateType::Triplet) {
97 return orb.BSETriplets();
98 } else {
99 throw std::runtime_error(
100 "Unsupported QMStateType in BSE::GetBSEEigenSystem");
101 }
102}
103
104std::string BSE::StateEnergiesHeader(const QMStateType& type) const {
105 if (type == QMStateType::Singlet) {
106 return " ====== singlet energies (eV) ====== ";
107 } else if (type == QMStateType::Triplet) {
108 return " ====== triplet energies (eV) ====== ";
109 } else {
110 throw std::runtime_error(
111 "Unsupported QMStateType in BSE::StateEnergiesHeader");
112 }
113}
114
115std::string BSE::StateShortLabel(const QMStateType& type) const {
116 if (type == QMStateType::Singlet) {
117 return "S";
118 } else if (type == QMStateType::Triplet) {
119 return "T";
120 } else {
121 throw std::runtime_error("Unsupported QMStateType in BSE::StateShortLabel");
122 }
123}
124
125std::string BSE::StateDynamicLabel(const QMStateType& type) const {
126 if (type == QMStateType::Singlet) {
127 return "singlet";
128 } else if (type == QMStateType::Triplet) {
129 return "triplet";
130 } else {
131 throw std::runtime_error(
132 "Unsupported QMStateType in BSE::StateDynamicLabel");
133 }
134}
135
136double BSE::ExchangePrefactor(const QMStateType& type) const {
137 if (type == QMStateType::Singlet) {
138 return 2.0;
139 } else if (type == QMStateType::Triplet) {
140 return 0.0;
141 } else {
142 throw std::runtime_error(
143 "Unsupported QMStateType in BSE::ExchangePrefactor");
144 }
145}
146
147Eigen::MatrixXd BSE::AdjustHqpSize(const Eigen::MatrixXd& Hqp,
148 const Eigen::VectorXd& RPAInputEnergies) {
149
150 Index hqp_size = bse_vtotal_ + bse_ctotal_;
151 Index gwsize = opt_.qpmax - opt_.qpmin + 1;
152 Index RPAoffset = opt_.vmin - opt_.rpamin;
153 Eigen::MatrixXd Hqp_BSE = Eigen::MatrixXd::Zero(hqp_size, hqp_size);
154
155 if (opt_.vmin >= opt_.qpmin) {
156 Index start = opt_.vmin - opt_.qpmin;
157 if (opt_.cmax <= opt_.qpmax) {
158 Hqp_BSE = Hqp.block(start, start, hqp_size, hqp_size);
159 } else {
160 Index virtoffset = gwsize - start;
161 Hqp_BSE.topLeftCorner(virtoffset, virtoffset) =
162 Hqp.block(start, start, virtoffset, virtoffset);
163
164 Index virt_extra = opt_.cmax - opt_.qpmax;
165 Hqp_BSE.diagonal().tail(virt_extra) =
166 RPAInputEnergies.segment(RPAoffset + virtoffset, virt_extra);
167 }
168 }
169
170 if (opt_.vmin < opt_.qpmin) {
171 Index occ_extra = opt_.qpmin - opt_.vmin;
172 Hqp_BSE.diagonal().head(occ_extra) =
173 RPAInputEnergies.segment(RPAoffset, occ_extra);
174
175 Hqp_BSE.block(occ_extra, occ_extra, gwsize, gwsize) = Hqp;
176
177 if (opt_.cmax > opt_.qpmax) {
178 Index virtoffset = occ_extra + gwsize;
179 Index virt_extra = opt_.cmax - opt_.qpmax;
180 Hqp_BSE.diagonal().tail(virt_extra) =
181 RPAInputEnergies.segment(RPAoffset + virtoffset, virt_extra);
182 }
183 }
184
185 return Hqp_BSE;
186}
187
189 const Eigen::VectorXd& RPAInputEnergies, double energy) {
190 RPA rpa = RPA(log_, Mmn_);
191 rpa.configure(opt_.homo, opt_.rpamin, opt_.rpamax);
192 rpa.setRPAInputEnergies(RPAInputEnergies);
193
194 Eigen::SelfAdjointEigenSolver<Eigen::MatrixXd> es(
195 rpa.calculate_epsilon_r(energy));
196 Mmn_.MultiplyRightWithAuxMatrix(es.eigenvectors());
197
198 epsilon_0_inv_ = Eigen::VectorXd::Zero(es.eigenvalues().size());
199 for (Index i = 0; i < es.eigenvalues().size(); ++i) {
200 if (es.eigenvalues()(i) > 1e-8) {
201 epsilon_0_inv_(i) = 1 / es.eigenvalues()(i);
202 }
203 }
204}
205
206template <typename BSE_OPERATOR>
209 opt.cmax = opt_.cmax;
210 opt.homo = opt_.homo;
211 opt.qpmin = opt_.qpmin;
212 opt.rpamin = opt_.rpamin;
213 opt.vmin = opt_.vmin;
214 H.configure(opt);
215}
216
223
225 orb.setTDAApprox(opt_.useTDA);
226 if (opt_.useTDA) {
228 } else {
230 }
232}
233
235 orb.setTDAApprox(opt_.useTDA);
236 if (opt_.useTDA) {
238 } else {
240 }
241}
242
244
248 << TimeStamp() << " Setup TDA singlet hamiltonian " << flush;
249 return solve_hermitian(Hs);
250}
251
258
265
266template <typename BSE_OPERATOR>
268
269 std::chrono::time_point<std::chrono::system_clock> start =
270 std::chrono::system_clock::now();
271
272 tools::EigenSystem result;
273
275
276 DS.set_correction(opt_.davidson_correction);
277 DS.set_tolerance(opt_.davidson_tolerance);
278 DS.set_size_update(opt_.davidson_update);
279 DS.set_iter_max(opt_.davidson_maxiter);
280 DS.set_max_search_space(10 * opt_.nmax);
281 DS.solve(h, opt_.nmax);
282 result.eigenvalues() = DS.eigenvalues();
283 result.eigenvectors() = DS.eigenvectors();
284
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;
288
289 XTP_LOG(Log::info, log_) << TimeStamp() << " Diagonalization done in "
290 << elapsed_time.count() << " secs" << flush;
291
292 return result;
293}
294
304
311 << TimeStamp() << " Setup Full triplet hamiltonian " << flush;
312 return Solve_nonhermitian_Davidson(A, B);
313}
314
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();
320
321 // operator
323
324 // Davidson solver
326 DS.set_correction(opt_.davidson_correction);
327 DS.set_tolerance(opt_.davidson_tolerance);
328 DS.set_size_update(opt_.davidson_update);
329 DS.set_iter_max(opt_.davidson_maxiter);
330 DS.set_max_search_space(10 * opt_.nmax);
331 DS.set_matrix_type("HAM");
332 Eigen::MatrixXd initial_guess = BuildFullBSEXRankedInitialGuess(
333 Aop.diagonal(), Bop.diagonal(), opt_.nmax);
334
335 DS.solve(Hop, opt_.nmax, initial_guess);
336
337 // results
338 tools::EigenSystem result;
339 result.eigenvalues() = DS.eigenvalues();
340 Eigen::MatrixXd tmpX = DS.eigenvectors().topRows(Aop.rows());
341 Eigen::MatrixXd tmpY = DS.eigenvectors().bottomRows(Bop.rows());
342
343 // // normalization so that eigenvector^2 - eigenvector2^2 = 1
344 Eigen::VectorXd normX = tmpX.colwise().squaredNorm();
345 Eigen::VectorXd normY = tmpY.colwise().squaredNorm();
346
347 Eigen::ArrayXd sqinvnorm = (normX - normY).array().inverse().cwiseSqrt();
348
349 result.eigenvectors() = tmpX * sqinvnorm.matrix().asDiagonal();
350 result.eigenvectors2() = tmpY * sqinvnorm.matrix().asDiagonal();
351
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;
355
356 XTP_LOG(Log::info, log_) << TimeStamp() << " Diagonalization done in "
357 << elapsed_time.count() << " secs" << flush;
358
359 return result;
360}
361
362void BSE::printFragInfo(const std::vector<QMFragment<BSE_Population> >& frags,
363 Index state) const {
364 for (const QMFragment<BSE_Population>& frag : frags) {
365 double dq = frag.value().H[state] + frag.value().E[state];
366 double qeff = dq + frag.value().Gs;
368 << boost::format(
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
373 << flush;
374 }
375 return;
376}
377
378void BSE::PrintWeights(const Eigen::VectorXd& weights) const {
380 for (Index i_bse = 0; i_bse < bse_size_; ++i_bse) {
381 double weight = weights(i_bse);
382 if (weight > opt_.min_print_weight) {
384 << boost::format(
385 " HOMO-%1$-3d -> LUMO+%2$-3d : %3$3.1f%%") %
386 (opt_.homo - vc.v(i_bse)) % (vc.c(i_bse) - opt_.homo - 1) %
387 (100.0 * weight)
388 << flush;
389 }
390 }
391 return;
392}
393
395 const Orbitals& orb) const {
396
398
399 Eigen::VectorXd oscs = orb.Oscillatorstrengths();
400 Interaction act = Analyze_eh_interaction(type, orb);
401
402 if (fragments.size() > 0) {
403 Lowdin low;
404 low.CalcChargeperFragment(fragments, orb, type);
405 }
406
407 const tools::EigenSystem& bse = GetBSEEigenSystem(type, orb);
408 const Eigen::VectorXd& energies = bse.eigenvalues();
409
410 double hrt2ev = tools::conv::hrt2ev;
411 XTP_LOG(Log::error, log_) << StateEnergiesHeader(type) << flush;
412 for (Index i = 0; i < opt_.nmax; ++i) {
413 Eigen::VectorXd weights = bse.eigenvectors().col(i).cwiseAbs2();
414 if (!orb.getTDAApprox()) {
415 weights -= bse.eigenvectors2().col(i).cwiseAbs2();
416 }
417
418 double osc = oscs[i];
420 << boost::format(
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") %
423 StateShortLabel(type) % (i + 1) % (hrt2ev * energies(i)) %
424 (1240.0 / (hrt2ev * energies(i))) %
425 (hrt2ev * act.qp_contrib(i)) %
426 (hrt2ev * act.exchange_contrib(i)) %
427 (hrt2ev * act.direct_contrib(i))
428 << flush;
429
430 const Eigen::Vector3d& trdip = orb.TransitionDipoles()[i];
432 << boost::format(
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
436 << flush;
437
438 PrintWeights(weights);
439 if (fragments.size() > 0) {
440 printFragInfo(fragments, i);
441 }
442
443 XTP_LOG(Log::error, log_) << flush;
444 }
445 return;
446}
447
449 const Orbitals& orb) const {
450
452 Interaction act = Analyze_eh_interaction(type, orb);
453
454 if (fragments.size() > 0) {
455 Lowdin low;
456 low.CalcChargeperFragment(fragments, orb, type);
457 }
458
459 const tools::EigenSystem& bse = GetBSEEigenSystem(type, orb);
460 const Eigen::VectorXd& energies = bse.eigenvalues();
461
462 XTP_LOG(Log::error, log_) << StateEnergiesHeader(type) << flush;
463 for (Index i = 0; i < opt_.nmax; ++i) {
464 Eigen::VectorXd weights = bse.eigenvectors().col(i).cwiseAbs2();
465 if (!orb.getTDAApprox()) {
466 weights -= bse.eigenvectors2().col(i).cwiseAbs2();
467 }
468
470 << boost::format(
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") %
473 StateShortLabel(type) % (i + 1) %
474 (tools::conv::hrt2ev * energies(i)) %
475 (1240.0 / (tools::conv::hrt2ev * energies(i))) %
478 << flush;
479
480 PrintWeights(weights);
481 if (fragments.size() > 0) {
482 printFragInfo(fragments, i);
483 }
484 XTP_LOG(Log::error, log_) << boost::format(" ") << flush;
485 }
486
487 return;
488}
489
490template <class OP>
491Eigen::VectorXd ExpValue(const Eigen::MatrixXd& state1, OP OPxstate2) {
492 return state1.cwiseProduct(OPxstate2.eval()).colwise().sum().transpose();
493}
494
495Eigen::VectorXd ExpValue(const Eigen::MatrixXd& state1,
496 const Eigen::MatrixXd& OPxstate2) {
497 return state1.cwiseProduct(OPxstate2).colwise().sum().transpose();
498}
499
500template <typename BSE_OPERATOR>
502 const QMStateType& type, const Orbitals& orb, const BSE_OPERATOR& H) const {
503
504 const tools::EigenSystem& BSECoefs = GetBSEEigenSystem(type, orb);
505
506 ExpectationValues expectation_values;
507
508 const Eigen::MatrixXd temp = H * BSECoefs.eigenvectors();
509
510 expectation_values.direct_term = ExpValue(BSECoefs.eigenvectors(), temp);
511 if (!orb.getTDAApprox()) {
512 expectation_values.direct_term +=
513 ExpValue(BSECoefs.eigenvectors2(), H * BSECoefs.eigenvectors2());
514 expectation_values.cross_term =
515 2 * ExpValue(BSECoefs.eigenvectors2(), temp);
516 } else {
517 expectation_values.cross_term = Eigen::VectorXd::Zero(0);
518 }
519 return expectation_values;
520}
521
522template <typename BSE_OPERATOR>
524 const QMState& state, const Orbitals& orb, const BSE_OPERATOR& H) const {
525
526 const tools::EigenSystem& BSECoefs = GetBSEEigenSystem(state.Type(), orb);
527
528 ExpectationValues expectation_values;
529
530 const Eigen::MatrixXd BSECoefs_state =
531 BSECoefs.eigenvectors().col(state.StateIdx());
532
533 const Eigen::MatrixXd temp = H * BSECoefs_state;
534
535 expectation_values.direct_term = ExpValue(BSECoefs_state, temp);
536
537 if (!orb.getTDAApprox()) {
538 const Eigen::MatrixXd BSECoefs2_state =
539 BSECoefs.eigenvectors2().col(state.StateIdx());
540
541 expectation_values.direct_term +=
542 ExpValue(BSECoefs2_state, H * BSECoefs2_state);
543 expectation_values.cross_term = 2 * ExpValue(BSECoefs2_state, temp);
544 } else {
545 expectation_values.cross_term = Eigen::VectorXd::Zero(0);
546 }
547
548 return expectation_values;
549}
550
551// Composition of the excitation energy in terms of QP, direct (screened),
552// and exchance contributions in the BSE
553// Full BSE:
554//
555// | A* | | H K | | A |
556// | -B* | | -K -H | | B | = A*.H.A + B*.H.B + 2A*.K.B
557//
558// with: H = H_qp + H_d + eta.H_x
559// K = H_d2 + eta.H_x
560//
561// reports composition for FULL BSE as
562// <FT> = A*.H_qp.A + B*.H_qp.B
563// <Kx> = eta.(A*.H_x.A + B*.H_x.B + 2A*.H_x.B)
564// <Kd> = A*.H_d.A + B*.H_d.B + 2A*.H_d2.B
566 const Orbitals& orb) const {
567 Interaction analysis;
568 {
571 ExpectationValues expectation_values =
572 ExpectationValue_Operator(type, orb, hqp);
573 analysis.qp_contrib = expectation_values.direct_term;
574 }
575 {
578 ExpectationValues expectation_values =
579 ExpectationValue_Operator(type, orb, hd);
580 analysis.direct_contrib = expectation_values.direct_term;
581 }
582 if (!orb.getTDAApprox()) {
585 ExpectationValues expectation_values =
586 ExpectationValue_Operator(type, orb, hd2);
587 analysis.direct_contrib += expectation_values.cross_term;
588 }
589
590 double xpref = ExchangePrefactor(type);
591 if (xpref != 0.0) {
594 ExpectationValues expectation_values =
595 ExpectationValue_Operator(type, orb, hx);
596 analysis.exchange_contrib = xpref * expectation_values.direct_term;
597 if (!orb.getTDAApprox()) {
598 analysis.exchange_contrib += xpref * expectation_values.cross_term;
599 }
600 } else {
601 analysis.exchange_contrib =
602 Eigen::VectorXd::Zero(analysis.direct_contrib.size());
603 }
604
605 return analysis;
606}
607
608// Dynamical Screening in BSE as perturbation to static excitation energies
609// as in Phys. Rev. B 80, 241405 (2009) for the TDA case
611 Orbitals& orb) {
612
613 const tools::EigenSystem& BSECoefs = GetBSEEigenSystem(type, orb);
614
615 const Eigen::VectorXd& RPAInputEnergies = orb.RPAInputEnergies();
616
617 // static case as reference
618 SetupDirectInteractionOperator(RPAInputEnergies, 0.0);
619 HdOperator Hd_static(epsilon_0_inv_, Mmn_, Hqp_);
620 configureBSEOperator(Hd_static);
621 ExpectationValues expectation_values =
622 ExpectationValue_Operator(type, orb, Hd_static);
623 Eigen::VectorXd Hd_static_contribution = expectation_values.direct_term;
624 if (!orb.getTDAApprox()) {
625 Hd2Operator Hd2_static(epsilon_0_inv_, Mmn_, Hqp_);
626 configureBSEOperator(Hd2_static);
627 expectation_values = ExpectationValue_Operator(type, orb, Hd2_static);
628 Hd_static_contribution += expectation_values.cross_term;
629 }
630
631 const Eigen::VectorXd& BSEenergies = BSECoefs.eigenvalues();
632
633 // initial copy of static BSE energies to dynamic
634 Eigen::VectorXd BSEenergies_dynamic = BSEenergies;
635
636 // recalculate Hd at the various energies
637 for (Index i_exc = 0; i_exc < BSEenergies.size(); i_exc++) {
638 XTP_LOG(Log::info, log_) << "Dynamical Screening BSE, Excitation " << i_exc
639 << " static " << BSEenergies(i_exc) << flush;
640
641 for (Index iter = 0; iter < max_dyn_iter_; iter++) {
642
643 // setup the direct operator with the last energy as screening frequency
644 double old_energy = BSEenergies_dynamic(i_exc);
645 SetupDirectInteractionOperator(RPAInputEnergies, old_energy);
647 configureBSEOperator(Hd_dyn);
648
649 // get the contribution of Hd for the dynamic case
650 QMState state(type, i_exc, false);
651 expectation_values = ExpectationValue_Operator_State(state, orb, Hd_dyn);
652 Eigen::VectorXd Hd_dynamic_contribution = expectation_values.direct_term;
653 if (!orb.getTDAApprox()) {
655 configureBSEOperator(Hd2_dyn);
656 expectation_values =
657 ExpectationValue_Operator_State(state, orb, Hd2_dyn);
658 Hd_dynamic_contribution += expectation_values.cross_term;
659 }
660
661 // new energy perturbatively
662 BSEenergies_dynamic(i_exc) = BSEenergies(i_exc) +
663 Hd_static_contribution(i_exc) -
664 Hd_dynamic_contribution(0);
665
667 << "Dynamical Screening BSE, excitation " << i_exc << " iteration "
668 << iter << " dynamic " << BSEenergies_dynamic(i_exc) << flush;
669
670 // check tolerance
671 if (std::abs(BSEenergies_dynamic(i_exc) - old_energy) < dyn_tolerance_) {
672 break;
673 }
674 }
675 }
676
677 double hrt2ev = tools::conv::hrt2ev;
678
679 if (type == QMStateType::Singlet) {
680 orb.BSESinglets_dynamic() = BSEenergies_dynamic;
681 XTP_LOG(Log::error, log_) << " ====== singlet energies with perturbative "
682 "dynamical screening (eV) ====== "
683 << flush;
684 Eigen::VectorXd oscs = orb.Oscillatorstrengths();
685 for (Index i = 0; i < opt_.nmax; ++i) {
686 double osc = oscs[i];
688 << boost::format(
689 " S(dynamic) = %1$4d Omega = %2$+1.12f eV lamdba = %3$+3.2f "
690 "nm f = %4$+1.4f") %
691 (i + 1) % (hrt2ev * BSEenergies_dynamic(i)) %
692 (1240.0 / (hrt2ev * BSEenergies_dynamic(i))) %
693 (osc * BSEenergies_dynamic(i) / BSEenergies(i))
694 << flush;
695 }
696
697 } else if (type == QMStateType::Triplet) {
698 orb.BSETriplets_dynamic() = BSEenergies_dynamic;
699 XTP_LOG(Log::error, log_) << " ====== triplet energies with perturbative "
700 "dynamical screening (eV) ====== "
701 << flush;
702 for (Index i = 0; i < opt_.nmax; ++i) {
704 << boost::format(
705 " T(dynamic) = %1$4d Omega = %2$+1.12f eV lamdba = %3$+3.2f "
706 "nm ") %
707 (i + 1) % (hrt2ev * BSEenergies_dynamic(i)) %
708 (1240.0 / (hrt2ev * BSEenergies_dynamic(i)))
709 << flush;
710 }
711
712 } else {
713 throw std::runtime_error(
714 "Unsupported QMStateType in BSE::Perturbative_DynamicalScreening");
715 }
716}
717
718} // namespace xtp
719} // namespace votca
const Eigen::MatrixXd & eigenvectors2() const
Definition eigensystem.h:36
const Eigen::VectorXd & eigenvalues() const
Definition eigensystem.h:30
const Eigen::MatrixXd & eigenvectors() const
Definition eigensystem.h:33
void Solve_singlets(Orbitals &orb) const
Definition bse.cc:224
void printFragInfo(const std::vector< QMFragment< BSE_Population > > &frags, Index state) const
Definition bse.cc:362
void PrintWeights(const Eigen::VectorXd &weights) const
Definition bse.cc:378
std::string StateDynamicLabel(const QMStateType &type) const
Definition bse.cc:125
double dyn_tolerance_
Definition bse.h:111
void configure_with_precomputed_screening(const options &opt, const Eigen::VectorXd &RPAEnergies, const Eigen::MatrixXd &Hqp_in, const Eigen::VectorXd &epsilon_0_inv)
Definition bse.cc:61
void Analyze_singlets(std::vector< QMFragment< BSE_Population > > fragments, const Orbitals &orb) const
Definition bse.cc:394
tools::EigenSystem Solve_triplets_BTDA() const
Definition bse.cc:305
TripletOperator_TDA getTripletOperator_TDA() const
Definition bse.cc:259
SingletOperator_TDA getSingletOperator_TDA() const
Definition bse.cc:252
ExpectationValues ExpectationValue_Operator_State(const QMState &state, const Orbitals &orb, const BSE_OPERATOR &H) const
Definition bse.cc:523
options opt_
Definition bse.h:90
tools::EigenSystem Solve_singlets_BTDA() const
Definition bse.cc:295
Index bse_vmax_
Definition bse.h:104
Index bse_cmin_
Definition bse.h:105
void Perturbative_DynamicalScreening(const QMStateType &type, Orbitals &orb)
Definition bse.cc:610
void Analyze_triplets(std::vector< QMFragment< BSE_Population > > fragments, const Orbitals &orb) const
Definition bse.cc:448
void SetupDirectInteractionOperator(const Eigen::VectorXd &DFTenergies, double energy)
Definition bse.cc:188
void configure(const options &opt, const Eigen::VectorXd &RPAEnergies, const Eigen::MatrixXd &Hqp_in)
Definition bse.cc:43
Eigen::MatrixXd Hqp_
Definition bse.h:116
tools::EigenSystem & GetBSEEigenSystem(const QMStateType &type, Orbitals &orb) const
Definition bse.cc:80
Eigen::VectorXd epsilon_0_inv_
Definition bse.h:113
ExpectationValues ExpectationValue_Operator(const QMStateType &type, const Orbitals &orb, const BSE_OPERATOR &H) const
Definition bse.cc:501
Interaction Analyze_eh_interaction(const QMStateType &type, const Orbitals &orb) const
Definition bse.cc:565
Index bse_ctotal_
Definition bse.h:108
double ExchangePrefactor(const QMStateType &type) const
Definition bse.cc:136
TCMatrix_gwbse & Mmn_
Definition bse.h:115
Index bse_size_
Definition bse.h:106
tools::EigenSystem Solve_singlets_TDA() const
Definition bse.cc:243
void configureBSEOperator(BSE_OPERATOR &H) const
Definition bse.cc:207
Index max_dyn_iter_
Definition bse.h:110
tools::EigenSystem solve_hermitian(BSE_OPERATOR &h) const
Definition bse.cc:267
void Solve_triplets(Orbitals &orb) const
Definition bse.cc:234
Logger & log_
Definition bse.h:103
tools::EigenSystem Solve_nonhermitian_Davidson(BSE_OPERATOR_A &Aop, BSE_OPERATOR_B &Bop) const
Definition bse.cc:316
Eigen::MatrixXd AdjustHqpSize(const Eigen::MatrixXd &Hqp_in, const Eigen::VectorXd &RPAInputEnergies)
Definition bse.cc:147
Index bse_vtotal_
Definition bse.h:107
std::string StateShortLabel(const QMStateType &type) const
Definition bse.cc:115
tools::EigenSystem Solve_triplets_TDA() const
Definition bse.cc:217
std::string StateEnergiesHeader(const QMStateType &type) const
Definition bse.cc:104
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_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.
Definition orbitals.h:47
const tools::EigenSystem & BSETriplets() const
Return read-only access to triplet BSE eigenpairs.
Definition orbitals.h:464
void CalcCoupledTransition_Dipoles()
Definition orbitals.cc:760
const tools::EigenSystem & BSESinglets() const
Return read-only access to singlet BSE eigenpairs.
Definition orbitals.h:477
bool getTDAApprox() const
Return whether the Tamm-Dancoff approximation is enabled.
Definition orbitals.h:388
Eigen::VectorXd Oscillatorstrengths() const
Definition orbitals.cc:643
const std::vector< Eigen::Vector3d > & TransitionDipoles() const
Return the stored transition dipole moments.
Definition orbitals.h:521
const Eigen::VectorXd & RPAInputEnergies() const
Return read-only access to the RPA input energies.
Definition orbitals.h:429
const Eigen::VectorXd & BSETriplets_dynamic() const
Return dynamically screened triplet BSE energies.
Definition orbitals.h:504
void setTDAApprox(bool usedTDA)
Enable or disable the Tamm-Dancoff approximation flag.
Definition orbitals.h:386
const Eigen::VectorXd & BSESinglets_dynamic() const
Return dynamically screened singlet BSE energies.
Definition orbitals.h:489
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.
Definition qmstate.h:135
Index StateIdx() const
Definition qmstate.h:157
const QMStateType & Type() const
Definition qmstate.h:154
void setRPAInputEnergies(const Eigen::VectorXd &rpaenergies)
Definition rpa.h:59
Eigen::MatrixXd calculate_epsilon_r(double frequency) const
Definition rpa.h:51
void configure(Index homo, Index rpamin, Index rpamax)
Definition rpa.h:39
Timestamp returns the current time as a string Example: cout << TimeStamp()
Definition logger.h:224
This class transforms a pair of indices v,c into a compound index I, via I=ctotal*v+c the fast dimens...
Definition vc2index.h:36
Index c(Index index) const
Definition vc2index.h:48
Index v(Index index) const
Definition vc2index.h:46
#define XTP_LOG(level, log)
Definition logger.h:40
const double hrt2ev
Definition constants.h:53
Charge transport classes.
Definition ERIs.h:28
Eigen::VectorXd ExpValue(const Eigen::MatrixXd &state1, OP OPxstate2)
Definition bse.cc:491
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
Definition bse.h:35
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
Definition bse.h:36
BSE_OPERATOR< 0, 2, 0, 1 > SingletOperator_BTDA_B
BSE_OPERATOR< 0, 1, 0, 0 > HxOperator
Provides a means for comparing floating point numbers.
Definition basebead.h:33
Eigen::Index Index
Definition types.h:26
Eigen::VectorXd direct_term
Definition bse.h:99
Eigen::VectorXd cross_term
Definition bse.h:100
Eigen::VectorXd qp_contrib
Definition bse.h:95
Eigen::VectorXd exchange_contrib
Definition bse.h:93
Eigen::VectorXd direct_contrib
Definition bse.h:94