votca 2024.1-dev
Loading...
Searching...
No Matches
convergenceacc.cc
Go to the documentation of this file.
1/*
2 * Copyright 2009-2022 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// Local VOTCA includes
22
23namespace votca {
24namespace xtp {
25
27 S_ = &S;
30 << TimeStamp() << " Smallest value of AOOverlap matrix is "
31 << S_->SmallestEigenValue() << std::flush;
33 << TimeStamp() << " Removed " << S_->Removedfunctions()
34 << " basisfunction from inverse overlap matrix" << std::flush;
35 return;
36}
37
38Eigen::MatrixXd ConvergenceAcc::Iterate(const Eigen::MatrixXd& dmat,
39 Eigen::MatrixXd& H,
40 tools::EigenSystem& MOs, double totE) {
41 Eigen::MatrixXd H_guess = Eigen::MatrixXd::Zero(H.rows(), H.cols());
42
43 if (int(mathist_.size()) == opt_.histlength) {
44 totE_.erase(totE_.begin() + maxerrorindex_);
45 mathist_.erase(mathist_.begin() + maxerrorindex_);
46 dmatHist_.erase(dmatHist_.begin() + maxerrorindex_);
47 }
48
49 totE_.push_back(totE);
51 double gap =
53 if ((diiserror_ > opt_.levelshiftend && opt_.levelshift > 0.0) ||
54 gap < 1e-6) {
56 }
57 }
58 const Eigen::MatrixXd& S = S_->Matrix();
59 Eigen::MatrixXd errormatrix =
60 Sminusahalf.transpose() * (H * dmat * S - S * dmat * H) * Sminusahalf;
61 diiserror_ = errormatrix.cwiseAbs().maxCoeff();
62
63 mathist_.push_back(H);
64 dmatHist_.push_back(dmat);
65
66 if (opt_.maxout) {
67 if (diiserror_ > maxerror_) {
69 maxerrorindex_ = mathist_.size() - 1;
70 }
71 }
72
73 diis_.Update(maxerrorindex_, errormatrix);
74 bool diis_error = false;
76 << TimeStamp() << " DIIs error " << getDIIsError() << std::flush;
77
79 << TimeStamp() << " Delta Etot " << getDeltaE() << std::flush;
80
82 opt_.usediis && mathist_.size() > 2) {
83 Eigen::VectorXd coeffs;
84 // use ADIIs if energy has risen a lot in current iteration
85
87 totE_.back() > 0.9 * totE_[totE_.size() - 2]) {
89 diis_error = !adiis_.Info();
91 << TimeStamp() << " Using ADIIS for next guess" << std::flush;
92
93 } else {
94 coeffs = diis_.CalcCoeff();
95 diis_error = !diis_.Info();
97 << TimeStamp() << " Using DIIS for next guess" << std::flush;
98 }
99 if (diis_error) {
101 << TimeStamp() << " (A)DIIS failed using mixing instead"
102 << std::flush;
103 H_guess = H;
104 } else {
105 for (Index i = 0; i < coeffs.size(); i++) {
106 if (std::abs(coeffs(i)) < 1e-8) {
107 continue;
108 }
109 H_guess += coeffs(i) * mathist_[i];
110 }
111 }
112
113 } else {
114 H_guess = H;
115 }
116
117 MOs = SolveFockmatrix(H_guess);
118
119 Eigen::MatrixXd dmatout = DensityMatrix(MOs);
120 if (diiserror_ > opt_.adiis_start || !opt_.usediis || diis_error ||
121 mathist_.size() <= 2) {
122 usedmixing_ = true;
123 dmatout =
124 opt_.mixingparameter * dmat + (1.0 - opt_.mixingparameter) * dmatout;
126 << TimeStamp() << " Using Mixing with alpha=" << opt_.mixingparameter
127 << std::flush;
128 } else {
129 usedmixing_ = false;
130 }
131 return dmatout;
132}
133
136 << TimeStamp() << " Convergence Options:" << std::flush;
138 << "\t\t Delta E [Ha]: " << opt_.Econverged << std::flush;
140 << "\t\t DIIS max error: " << opt_.error_converged << std::flush;
141 if (opt_.usediis) {
143 << "\t\t DIIS histlength: " << opt_.histlength << std::flush;
145 << "\t\t ADIIS start: " << opt_.adiis_start << std::flush;
147 << "\t\t DIIS start: " << opt_.diis_start << std::flush;
148 std::string del = "oldest";
149 if (opt_.maxout) {
150 del = "largest";
151 }
153 << "\t\t Deleting " << del << " element from DIIS hist" << std::flush;
154 }
156 << "\t\t Levelshift[Ha]: " << opt_.levelshift << std::flush;
158 << "\t\t Levelshift end: " << opt_.levelshiftend << std::flush;
160 << "\t\t Mixing Parameter alpha: " << opt_.mixingparameter << std::flush;
161}
162
164 const Eigen::MatrixXd& H) const {
165 // transform to orthogonal for
166 Eigen::MatrixXd H_ortho = Sminusahalf.transpose() * H * Sminusahalf;
167 Eigen::SelfAdjointEigenSolver<Eigen::MatrixXd> es(H_ortho);
168
169 if (es.info() != Eigen::ComputationInfo::Success) {
170 throw std::runtime_error("Matrix Diagonalisation failed. DiagInfo" +
171 std::to_string(es.info()));
172 }
173
174 tools::EigenSystem result;
175 result.eigenvalues() = es.eigenvalues();
176
177 result.eigenvectors() = Sminusahalf * es.eigenvectors();
178 return result;
179}
180
181void ConvergenceAcc::Levelshift(Eigen::MatrixXd& H,
182 const Eigen::MatrixXd& MOs_old) const {
183 if (opt_.levelshift < 1e-9) {
184 return;
185 }
186 Eigen::VectorXd virt = Eigen::VectorXd::Zero(H.rows());
187 for (Index i = nocclevels_; i < H.rows(); i++) {
188 virt(i) = opt_.levelshift;
189 }
190
192 << TimeStamp() << " Using levelshift:" << opt_.levelshift << " Hartree"
193 << std::flush;
194 Eigen::MatrixXd vir = S_->Matrix() * MOs_old * virt.asDiagonal() *
195 MOs_old.transpose() * S_->Matrix();
196 H += vir;
197 return;
198}
199
201 const tools::EigenSystem& MOs) const {
202 Eigen::MatrixXd result;
203 if (opt_.mode == KSmode::closed) {
205 } else if (opt_.mode == KSmode::open) {
207 } else if (opt_.mode == KSmode::fractional) {
208 result = DensityMatrixGroundState_frac(MOs);
209 }
210 return result;
211}
212
214 const Eigen::MatrixXd& MOs) const {
215 const Eigen::MatrixXd occstates = MOs.leftCols(nocclevels_);
216 Eigen::MatrixXd dmatGS = 2.0 * occstates * occstates.transpose();
217 return dmatGS;
218}
219
221 const Eigen::MatrixXd& MOs) const {
222 if (nocclevels_ == 0) {
223 return Eigen::MatrixXd::Zero(MOs.rows(), MOs.rows());
224 }
225 Eigen::MatrixXd occstates = MOs.leftCols(nocclevels_);
226 Eigen::MatrixXd dmatGS = occstates * occstates.transpose();
227 return dmatGS;
228}
229
231 const tools::EigenSystem& MOs) const {
232 if (opt_.numberofelectrons == 0) {
233 return Eigen::MatrixXd::Zero(MOs.eigenvectors().rows(),
234 MOs.eigenvectors().rows());
235 }
236
237 Eigen::VectorXd occupation = Eigen::VectorXd::Zero(MOs.eigenvalues().size());
238 std::vector<std::vector<Index> > degeneracies;
239 double buffer = 1e-4;
240 degeneracies.push_back(std::vector<Index>{0});
241 for (Index i = 1; i < occupation.size(); i++) {
242 if (MOs.eigenvalues()(i) <
243 MOs.eigenvalues()(degeneracies[degeneracies.size() - 1][0]) + buffer) {
244 degeneracies[degeneracies.size() - 1].push_back(i);
245 } else {
246 degeneracies.push_back(std::vector<Index>{i});
247 }
248 }
249 Index numofelec = opt_.numberofelectrons;
250 for (const std::vector<Index>& deglevel : degeneracies) {
251 Index numofpossibleelectrons = 2 * Index(deglevel.size());
252 if (numofpossibleelectrons <= numofelec) {
253 for (Index i : deglevel) {
254 occupation(i) = 2;
255 }
256 numofelec -= numofpossibleelectrons;
257 } else {
258 double occ = double(numofelec) / double(deglevel.size());
259 for (Index i : deglevel) {
260 occupation(i) = occ;
261 }
262 break;
263 }
264 }
265 Eigen::MatrixXd dmatGS = MOs.eigenvectors() * occupation.asDiagonal() *
266 MOs.eigenvectors().transpose();
267 return dmatGS;
268}
269
270} // namespace xtp
271} // namespace votca
const Eigen::VectorXd & eigenvalues() const
Definition eigensystem.h:30
const Eigen::MatrixXd & eigenvectors() const
Definition eigensystem.h:33
Eigen::VectorXd CalcCoeff(const std::vector< Eigen::MatrixXd > &dmathist, const std::vector< Eigen::MatrixXd > &mathist)
Definition adiis.cc:32
bool Info()
Definition adiis.h:39
Eigen::MatrixXd Pseudo_InvSqrt(double etol)
Definition aomatrix.cc:28
const Eigen::MatrixXd & Matrix() const
Definition aomatrix.h:52
double SmallestEigenValue() const
Definition aomatrix.h:56
Index Removedfunctions() const
Definition aomatrix.h:55
Eigen::MatrixXd DensityMatrix(const tools::EigenSystem &MOs) const
Eigen::MatrixXd DensityMatrixGroundState_unres(const Eigen::MatrixXd &MOs) const
std::vector< Eigen::MatrixXd > mathist_
Eigen::MatrixXd Iterate(const Eigen::MatrixXd &dmat, Eigen::MatrixXd &H, tools::EigenSystem &MOs, double totE)
tools::EigenSystem SolveFockmatrix(const Eigen::MatrixXd &H) const
void Levelshift(Eigen::MatrixXd &H, const Eigen::MatrixXd &MOs_old) const
Eigen::MatrixXd DensityMatrixGroundState_frac(const tools::EigenSystem &MOs) const
std::vector< double > totE_
void setOverlap(AOOverlap &S, double etol)
Eigen::MatrixXd DensityMatrixGroundState(const Eigen::MatrixXd &MOs) const
std::vector< Eigen::MatrixXd > dmatHist_
bool Info()
Definition diis.h:40
void Update(Index maxerrorindex, const Eigen::MatrixXd &errormatrix)
Definition diis.cc:29
Eigen::VectorXd CalcCoeff()
Definition diis.cc:53
Timestamp returns the current time as a string Example: cout << TimeStamp()
Definition logger.h:224
#define XTP_LOG(level, log)
Definition logger.h:40
base class for all analysis tools
Definition basebead.h:33
Eigen::Index Index
Definition types.h:26