votca 2026-dev
Loading...
Searching...
No Matches
diis.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 <iostream>
22
23// Local VOTCA includes
24#include "votca/xtp/diis.h"
25
26namespace votca {
27namespace xtp {
28
36
37// Update the Pulay error history. The scalar products stored in Diis_Bs_
38// form the DIIS B matrix with elements
39//
40// B_ij = <R_i | R_j> = Tr[R_i^T R_j],
41//
42// where R_i is the commutator residual of iteration i.
43void DIIS::Update(Index maxerrorindex, const Eigen::MatrixXd& errormatrix) {
44
45 if (int(errormatrixhist_.size()) == histlength_) {
46 errormatrixhist_.erase(errormatrixhist_.begin() + maxerrorindex);
47 Diis_Bs_.erase(Diis_Bs_.begin() + maxerrorindex);
48 for (std::vector<double>& subvec : Diis_Bs_) {
49 subvec.erase(subvec.begin() + maxerrorindex);
50 }
51 }
52
53 errormatrixhist_.push_back(errormatrix);
54
55 std::vector<double> Bijs;
56 for (Index i = 0; i < Index(errormatrixhist_.size()) - 1; i++) {
57 double value =
58 errormatrix.cwiseProduct((errormatrixhist_[i]).transpose()).sum();
59 Bijs.push_back(value);
60 Diis_Bs_[i].push_back(value);
61 }
62 Bijs.push_back(errormatrix.cwiseProduct(errormatrix.transpose()).sum());
63 Diis_Bs_.push_back(Bijs);
64 return;
65}
66
67// Solve the standard constrained DIIS system
68//
69// [ B -1 ] [c] [0]
70// [ -1 0 ] [l] = [-1]
71//
72// to obtain extrapolation coefficients c whose sum is one.
73Eigen::VectorXd DIIS::CalcCoeff() {
74 success = true;
75
76 Index size = 0;
77 if (!errormatrixhist_alpha_.empty()) {
78 size = Index(errormatrixhist_alpha_.size());
79 } else {
80 size = Index(errormatrixhist_.size());
81 }
82
83 if (size < 2) {
84 success = false;
85 return Eigen::VectorXd();
86 }
87
88 Eigen::MatrixXd B = Eigen::MatrixXd::Zero(size, size);
89
90 for (Index i = 0; i < size; ++i) {
91 for (Index j = 0; j <= i; ++j) {
92 B(i, j) = Diis_Bs_[i][j];
93 if (i != j) {
94 B(j, i) = B(i, j);
95 }
96 }
97 }
98
99 Eigen::SelfAdjointEigenSolver<Eigen::MatrixXd> es(B);
100 if (es.info() != Eigen::Success) {
101 success = false;
102 return Eigen::VectorXd();
103 }
104
105 Eigen::MatrixXd eigenvectors = Eigen::MatrixXd::Zero(size, size);
106
107 for (Index i = 0; i < size; ++i) {
108 double norm = es.eigenvectors().col(i).sum();
109 if (std::abs(norm) < 1e-14) {
110 eigenvectors.col(i) = es.eigenvectors().col(i);
111 } else {
112 eigenvectors.col(i) = es.eigenvectors().col(i) / norm;
113 }
114 }
115
116 Eigen::VectorXd errors =
117 (eigenvectors.transpose() * B * eigenvectors).diagonal().cwiseAbs();
118
119 constexpr double MaxWeight = 10.0;
120 Index mincoeff = 0;
121 success = false;
122
123 for (Index i = 0; i < errors.size(); ++i) {
124 errors.minCoeff(&mincoeff);
125 if (std::abs(eigenvectors.col(mincoeff).maxCoeff()) > MaxWeight) {
126 errors[mincoeff] = std::numeric_limits<double>::max();
127 } else {
128 success = true;
129 break;
130 }
131 }
132
133 if (!success) {
134 return Eigen::VectorXd();
135 }
136
137 Eigen::VectorXd coeffs = eigenvectors.col(mincoeff);
138
139 if (coeffs.size() == 0 || std::abs(coeffs[coeffs.size() - 1]) < 0.001) {
140 success = false;
141 return Eigen::VectorXd();
142 }
143
144 return coeffs;
145}
146
147// Unrestricted DIIS update. The alpha and beta residual overlaps are added
148// so that B_ij represents the spin-summed residual metric used in the UKS
149// extrapolation.
150void DIIS::Update(Index maxerrorindex, const Eigen::MatrixXd& errormatrix_alpha,
151 const Eigen::MatrixXd& errormatrix_beta) {
152
153 if (int(errormatrixhist_alpha_.size()) == histlength_) {
155 maxerrorindex);
156 errormatrixhist_beta_.erase(errormatrixhist_beta_.begin() + maxerrorindex);
157 Diis_Bs_.erase(Diis_Bs_.begin() + maxerrorindex);
158 for (std::vector<double>& subvec : Diis_Bs_) {
159 subvec.erase(subvec.begin() + maxerrorindex);
160 }
161 }
162
163 errormatrixhist_alpha_.push_back(errormatrix_alpha);
164 errormatrixhist_beta_.push_back(errormatrix_beta);
165
166 std::vector<double> Bijs;
167 for (Index i = 0; i < Index(errormatrixhist_alpha_.size()) - 1; ++i) {
168 double value =
169 errormatrix_alpha.cwiseProduct(errormatrixhist_alpha_[i].transpose())
170 .sum() +
171 errormatrix_beta.cwiseProduct(errormatrixhist_beta_[i].transpose())
172 .sum();
173 Bijs.push_back(value);
174 Diis_Bs_[i].push_back(value);
175 }
176
177 double self =
178 errormatrix_alpha.cwiseProduct(errormatrix_alpha.transpose()).sum() +
179 errormatrix_beta.cwiseProduct(errormatrix_beta.transpose()).sum();
180
181 Bijs.push_back(self);
182 Diis_Bs_.push_back(Bijs);
183}
184
185} // namespace xtp
186} // namespace votca
bool success
Definition diis.h:62
std::vector< Eigen::MatrixXd > errormatrixhist_alpha_
Definition diis.h:66
std::vector< Eigen::MatrixXd > errormatrixhist_
Definition diis.h:65
void Update(Index maxerrorindex, const Eigen::MatrixXd &errormatrix)
Definition diis.cc:43
std::vector< Eigen::MatrixXd > errormatrixhist_beta_
Definition diis.h:67
std::vector< std::vector< double > > Diis_Bs_
Definition diis.h:64
Index histlength_
Definition diis.h:63
Eigen::VectorXd CalcCoeff()
Definition diis.cc:73
Charge transport classes.
Definition ERIs.h:28
Provides a means for comparing floating point numbers.
Definition basebead.h:33
Eigen::Index Index
Definition types.h:26