votca 2024.2-dev
Loading...
Searching...
No Matches
erdiabatization.cc
Go to the documentation of this file.
1/*
2 * Copyright 2009-2020 The VOTCA Development Team (http://www.votca.org)
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *
16 */
17
18// VOTCA includes
20#include "votca/xtp/ERIs.h"
23
24using boost::format;
25using std::flush;
26
27namespace votca {
28namespace xtp {
29
31
32 // Check on dftbasis
34 throw std::runtime_error("Different DFT basis for the two input file.");
35 } else {
38 << TimeStamp() << " Data was created with basis set "
39 << orbitals1_.getDFTbasisName() << flush;
40 }
41
42 // Check on auxbasis
46 hasRI_ = true;
47 } else {
48 throw std::runtime_error(
49 "Different DFT aux-basis for the two input file.");
50 }
51 } else {
53 << "No auxbasis for file1: This will affect perfomances " << flush;
54 hasRI_ = false;
55 }
56
57 // check BSE indices
59 throw std::runtime_error("Different BSE vmin for the two input file.");
60 }
61
63 throw std::runtime_error("Different BSE vmax for the two input file.");
64 }
65
67 throw std::runtime_error("Different BSE cmin for the two input file.");
68 }
69
71 throw std::runtime_error("Different BSE cmax for the two input file.");
72 }
73
74 // Use different RI initialization according to what is in the orb files.
75 if (hasRI_ && useRI_) {
76 XTP_LOG(Log::error, *pLog_) << TimeStamp() << " Using RI " << flush;
78 } else {
80 }
81}
82
94
95double ERDiabatization::CalculateR(const Eigen::MatrixXd& D_JK,
96 const Eigen::MatrixXd& D_LM) const {
97
98 Eigen::MatrixXd contracted;
99 if (hasRI_ && useRI_) {
100 contracted = eris_.CalculateERIs_3c(D_LM);
101 } else {
102 contracted = eris_.CalculateERIs_4c(D_LM, 1e-12);
103 }
104
105 return D_JK.cwiseProduct(contracted).sum();
106}
107
108Eigen::MatrixXd ERDiabatization::CalculateU(const double phi) const {
109 Eigen::MatrixXd U(2, 2);
110 U(0, 0) = std::cos(phi);
111 U(0, 1) = -1.0 * std::sin(phi);
112 U(1, 0) = std::sin(phi);
113 U(1, 1) = std::cos(phi);
114 return U;
115}
116
117std::pair<Eigen::VectorXd, Eigen::MatrixXd>
118 ERDiabatization::Calculate_diabatic_H(const double angle) const {
119 Eigen::VectorXd ad_energies(2);
120 ad_energies << E1_, E2_;
121
123 << TimeStamp() << "Rotation angle (degrees) " << angle * 57.2958 << flush;
124
125 Eigen::MatrixXd U = CalculateU(angle);
126 return std::pair<Eigen::VectorXd, Eigen::MatrixXd>(
127 ad_energies, U.transpose() * ad_energies.asDiagonal() * U);
128}
129
131 Eigen::Tensor<double, 4> rtensor = CalculateRtensor();
132
133 double A_12 =
134 rtensor(0, 1, 0, 1) - 0.25 * (rtensor(0, 0, 0, 0) + rtensor(1, 1, 1, 1) -
135 2. * rtensor(0, 0, 1, 1));
136 double B_12 = rtensor(0, 0, 0, 1) - rtensor(1, 1, 0, 1);
137
138 double cos4alpha = -A_12 / (std::sqrt(A_12 * A_12 + B_12 * B_12));
139
140 // also calculate sin4alpha
141 double sin4alpha = B_12 / (std::sqrt(A_12 * A_12 + B_12 * B_12));
142
143 // In some cases acos may give the wrong solution, that das not maych
144 // sin4alpha Instead, follow procedure in original ER paper
145 double sqroot = std::sqrt(1.0 - 0.5 * (1.0 - cos4alpha));
146 double x_squared_plus = 0.5 * (1.0 + sqroot);
147 double x_squared_minus = 0.5 * (1.0 - sqroot);
148
149 double x1 = sqrt(x_squared_plus);
150 double y1 = sqrt(1.0 - x_squared_plus);
151
152 double x2 = sqrt(x_squared_minus);
153 double y2 = sqrt(1.0 - x_squared_minus);
154
155 double test1 = 4.0 * x1 * y1 * (x1 * x1 - y1 * y1);
156 double test2 = 4.0 * x2 * y2 * (x2 * x2 - y2 * y2);
157
158 double cos_alpha0 = 0;
159 double sin_alpha0 = 0;
160
161 // check which (x,y) pair matches sin(4alpha)
162 if (std::abs(test1 - sin4alpha) < 1e-4) {
163 cos_alpha0 = x1;
164 sin_alpha0 = y1;
165 } else if (std::abs(test2 - sin4alpha) < 1e-4) {
166 cos_alpha0 = x2;
167 sin_alpha0 = y2;
168 } else {
169 XTP_LOG(Log::debug, *pLog_) << "Can't find correct angle " << flush;
170 }
171
173 << "Coupling element directly: "
174 << cos_alpha0 * sin_alpha0 * (E2_ - E1_) * votca::tools::conv::hrt2ev
175 << flush;
176
177 double angle = std::acos(cos_alpha0);
178
179 XTP_LOG(Log::debug, *pLog_) << "B12 " << B_12 << flush;
180 XTP_LOG(Log::debug, *pLog_) << "A12 " << A_12 << flush;
181
183 << "angle MAX (degrees) " << angle * 57.2958 << flush;
184
185 return angle;
186}
187
188Eigen::Tensor<double, 4> ERDiabatization::CalculateRtensor() const {
189 Eigen::Tensor<double, 4> r_tensor(2, 2, 2, 2);
190
191 // get a transition density calculator object
193 tdmat.configure();
194
195 // define QM states
196 QMState state1 = QMState(qmtype_, state_idx_1_ - 1, false);
197 QMState state2 = QMState(qmtype_, state_idx_2_ - 1, false);
198 std::vector<QMState> states;
199 states.push_back(state1);
200 states.push_back(state2);
201
202 // determine tensor elements
203 for (Index J = 0; J < 2; J++) {
204 for (Index K = 0; K < 2; K++) {
205 Eigen::MatrixXd D_JK = tdmat.Matrix(states[J], states[K]);
206 if (J == 0 && K == 0) {
208 }
209 if (J == 1 && K == 1) {
211 }
212 for (Index L = 0; L < 2; L++) {
213 for (Index M = 0; M < 2; M++) {
214 Eigen::MatrixXd D_LM = tdmat.Matrix(states[L], states[M]);
215 if (L == 0 && M == 0) {
217 }
218 if (L == 1 && M == 1) {
220 }
221 r_tensor(J, K, L, M) = CalculateR(D_JK, D_LM);
222 }
223 }
224 }
225 }
226 return r_tensor;
227}
228
229} // namespace xtp
230} // namespace votca
const Eigen::VectorXd & eigenvalues() const
Definition eigensystem.h:30
Eigen::Tensor< double, 4 > CalculateRtensor() const
std::pair< Eigen::VectorXd, Eigen::MatrixXd > Calculate_diabatic_H(const double angle) const
double CalculateR(const Eigen::MatrixXd &D_JK, const Eigen::MatrixXd &D_LM) const
Eigen::MatrixXd CalculateU(const double phi) const
Eigen::MatrixXd CalculateERIs_3c(const Eigen::MatrixXd &DMAT) const
Definition ERIs.cc:80
void Initialize_4c(const AOBasis &dftbasis)
Definition ERIs.cc:32
void Initialize(const AOBasis &dftbasis, const AOBasis &auxbasis)
Definition ERIs.cc:27
Eigen::MatrixXd CalculateERIs_4c(const Eigen::MatrixXd &DMAT, double error) const
Definition ERIs.h:56
Index getBSEvmax() const
Definition orbitals.h:286
const tools::EigenSystem & BSETriplets() const
Definition orbitals.h:324
Index getBSEcmin() const
Definition orbitals.h:288
bool hasAuxbasisName() const
Definition orbitals.h:234
const tools::EigenSystem & BSESinglets() const
Definition orbitals.h:334
Index getBSEcmax() const
Definition orbitals.h:290
const AOBasis & getAuxBasis() const
Definition orbitals.h:218
Index getBSEvmin() const
Definition orbitals.h:284
const std::string getAuxbasisName() const
Definition orbitals.h:238
Eigen::MatrixXd DensityMatrixGroundState() const
Definition orbitals.cc:183
const std::string & getDFTbasisName() const
Definition orbitals.h:202
const AOBasis & getDftBasis() const
Definition orbitals.h:208
void FromString(const std::string &statetypestring)
Definition qmstate.cc:103
Identifier for QMstates. Strings like S1 are converted into enum +zero indexed int.
Definition qmstate.h:132
Timestamp returns the current time as a string Example: cout << TimeStamp()
Definition logger.h:224
Generalized transition densities tools for different excited states.
Eigen::MatrixXd Matrix(QMState state1, QMState state2)
#define XTP_LOG(level, log)
Definition logger.h:40
const double hrt2ev
Definition constants.h:53
base class for all analysis tools
Definition basebead.h:33
Eigen::Index Index
Definition types.h:26