190 void extrapolate(D& x, D& error,
bool extrapolate_error =
false) {
191 using namespace ::libint2::diis;
193 const value_type zero_determinant =
194 std::numeric_limits<value_type>::epsilon();
195 const value_type zero_norm = 1.0e-10;
199 const bool do_mixing = (mixing_fraction != 0.0);
200 const value_type scale = 1.0 + damping_factor;
203 if (errors_.size() == ndiis) {
207 if (not x_extrap_.empty()) x_extrap_.pop_front();
208 EigenMatrixX Bcrop = B_.bottomRightCorner(ndiis - 1, ndiis - 1);
209 Bcrop.conservativeResize(ndiis, ndiis);
215 errors_.push_back(error);
216 const unsigned int nvec = errors_.size();
217 assert(x_.size() == errors_.size());
220 for (
unsigned int i = 0; i < nvec - 1; i++)
221 B_(i, nvec - 1) = B_(nvec - 1, i) =
222 dot_product(errors_[i], errors_[nvec - 1]);
223 B_(nvec - 1, nvec - 1) = dot_product(errors_[nvec - 1], errors_[nvec - 1]);
226 if (not x_extrap_.empty() && do_mixing) {
228 axpy(x, (1.0 - mixing_fraction), x_[0]);
229 axpy(x, mixing_fraction, x_extrap_[0]);
231 }
else if (iter > start && (((iter - start) % ngroup) <
238 unsigned int nskip = 0;
242 const unsigned int rank = nvec - nskip + 1;
245 EigenMatrixX A(rank, rank);
246 A.col(0).setConstant(-1.0);
247 A.row(0).setConstant(-1.0);
249 EigenVectorX rhs = EigenVectorX::Zero(rank);
252 value_type norm = 1.0;
253 if (B_(nskip, nskip) > zero_norm) norm = 1.0 / B_(nskip, nskip);
255 A.block(1, 1, rank - 1, rank - 1) =
256 B_.block(nskip, nskip, rank - 1, rank - 1) * norm;
257 A.diagonal() *= scale;
266 std::cout <<
"DIIS: iter=" << iter <<
" nskip=" << nskip <<
" nvec=" << nvec << std::endl;
267 std::cout <<
"DIIS: B=" << B_ << std::endl;
268 std::cout <<
"DIIS: A=" << A << std::endl;
269 std::cout <<
"DIIS: rhs=" << rhs << std::endl;
273 Eigen::ColPivHouseholderQR<EigenMatrixX> A_QR = A.colPivHouseholderQr();
275 absdetA = A_QR.absDeterminant();
281 }
while (absdetA < zero_determinant &&
285 if (absdetA < zero_determinant) {
286 std::ostringstream oss;
287 oss <<
"DIIS::extrapolate: poorly-conditioned system, |A| = "
289 throw std::domain_error(oss.str());
295 for (
unsigned int k = nskip, kk = 1; k < nvec; ++k, ++kk) {
296 if (not do_mixing || x_extrap_.empty()) {
299 axpy(x, c[kk], x_[k]);
300 if (extrapolate_error) axpy(error, c[kk], errors_[k]);
302 axpy(x, c[kk] * (1.0 - mixing_fraction), x_[k]);
303 axpy(x, c[kk] * mixing_fraction, x_extrap_[k]);
310 if (do_mixing) x_extrap_.push_back(x);