26 #ifndef TILEDARRAY_ALGEBRA_DIIS_H__INCLUDED 27 #define TILEDARRAY_ALGEBRA_DIIS_H__INCLUDED 32 #include "../dist_array.h" 112 unsigned int ngrdiis=1,
114 error_(0), errorset_(false),
115 start(strt), ndiis(ndi),
116 iter(0), ngroup(ngr),
138 bool extrapolate_error =
false)
148 const unsigned int nvec = errors_.size();
152 "DIIS: numbers of guess and error vectors do not match, likely due to a programming error");
155 if (extrapolate_error && (mixing_fraction == 0.0 || x_extrap_.empty())) {
156 for (
unsigned int k=nskip_, kk=1; k < nvec; ++k, ++kk) {
157 axpy(error, C_[kk], errors_[k]);
172 unsigned int nskip = 0,
173 bool increase_iter =
false) {
178 const bool do_mixing = (mixing_fraction != 0.0);
181 if (x_.size() == ndiis) {
183 if (not x_extrap_.empty()) x_extrap_.pop_front();
190 if (not x_extrap_.empty() && do_mixing) {
192 axpy(x, (1.0-mixing_fraction), x_[0]);
193 axpy(x, mixing_fraction, x_extrap_[0]);
196 else if (iter > start && (((iter - start) % ngroup) < ngroupdiis)) {
198 const unsigned int nvec = x_.size();
199 const unsigned int rank = nvec - nskip + 1;
202 "DIIS: numbers of coefficients and x's do not match");
204 for (
unsigned int k=nskip, kk=1; k < nvec; ++k, ++kk) {
205 if (not do_mixing || x_extrap_.empty()) {
207 axpy(x, c[kk], x_[k]);
209 axpy(x, c[kk] * (1.0 - mixing_fraction), x_[k]);
210 axpy(x, c[kk] * mixing_fraction, x_extrap_[k]);
217 if (do_mixing) x_extrap_.push_back(x);
226 bool increase_iter =
false) {
236 if (errors_.size() == ndiis) {
238 EigenMatrixX Bcrop = B_.bottomRightCorner(ndiis-1,ndiis-1);
239 Bcrop.conservativeResize(ndiis,ndiis);
244 errors_.push_back(error);
245 const unsigned int nvec = errors_.size();
248 for (
unsigned int i=0; i < nvec-1; i++)
249 B_(i,nvec-1) = B_(nvec-1,i) =
dot_product(errors_[i], errors_[nvec-1]);
250 B_(nvec-1,nvec-1) =
dot_product(errors_[nvec-1], errors_[nvec-1]);
253 if (iter > start && (((iter - start) % ngroup) < ngroupdiis)) {
259 const unsigned int rank = nvec - nskip_ + 1;
265 A.col(0).setConstant(-1.0);
266 A.row(0).setConstant(-1.0);
272 if (
std::abs(B_(nskip_,nskip_)) > zero_norm)
275 A.block(1, 1, rank-1, rank-1) = B_.block(nskip_, nskip_, rank-1, rank-1) *
norm;
276 A.diagonal() *=
scale;
285 std::cout <<
"DIIS: iter=" << iter <<
" nskip=" << nskip <<
" nvec=" << nvec << std::endl;
286 std::cout <<
"DIIS: B=" << B_ << std::endl;
287 std::cout <<
"DIIS: A=" << A << std::endl;
288 std::cout <<
"DIIS: rhs=" << rhs << std::endl;
292 Eigen::ColPivHouseholderQR<EigenMatrixX> A_QR = A.colPivHouseholderQr();
293 C_ = A_QR.solve(rhs);
294 absdetA = A_QR.absDeterminant();
300 }
while (absdetA < zero_determinant && nskip_ < nvec);
303 if (absdetA < zero_determinant) {
304 std::ostringstream oss;
305 oss <<
"DIIS::extrapolate: poorly-conditioned system, |A| = " << absdetA;
306 throw std::domain_error(oss.str());
310 parameters_computed_ =
true;
319 if (start > iter) start = iter+1;
325 const bool do_mixing = (mixing_fraction != 0.0);
326 if (do_mixing) x_extrap_.push_front(*
data);
333 "DIIS: empty coefficients, because they have not been computed");
351 unsigned int ngroupdiis;
357 bool parameters_computed_;
361 std::deque<D> errors_;
362 std::deque<D> x_extrap_;
364 void set_error(
scalar_type e) { error_ = e; errorset_ =
true; }
370 B_ = EigenMatrixX::Zero(ndiis,ndiis);
372 parameters_computed_ =
false;
389 #endif // TILEDARRAY_ALGEBRA_DIIS_H__INCLUDED Eigen::Matrix< value_type, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor > EigenMatrixX
auto data(T &t)
Container data pointer accessor.
DIIS(unsigned int strt=1, unsigned int ndi=5, scalar_type dmp=0, unsigned int ngr=1, unsigned int ngrdiis=1, scalar_type mf=0)
Constructor.
void extrapolate(D &x, const EigenVectorX &c, unsigned int nskip=0, bool increase_iter=false)
void scale(DistArray< Tile, Policy > &a, typename DistArray< Tile, Policy >::element_type scaling_factor)
decltype(auto) norm(const Tile< Arg > &arg)
Vector 2-norm of a tile.
bool parameters_computed()
calling this function returns whether diis parameters C_ and nskip_ have been computed ...
auto abs(const ComplexConjugate< T > &a)
Eigen::Matrix< value_type, Eigen::Dynamic, 1 > EigenVectorX
void start_extrapolation()
unsigned int get_nskip()
calling this function returns number of skipped vectors in extrapolation
typename TiledArray::detail::scalar_type< T >::type scalar_t
detail::scalar_t< value_type > scalar_type
void axpy(DistArray< Tile, Policy > &y, typename DistArray< Tile, Policy >::element_type a, const DistArray< Tile, Policy > &x)
void zero(DistArray< Tile, Policy > &a)
D::element_type value_type
DIIS (‘‘direct inversion of iterative subspace’’) extrapolation.
void extrapolate(D &x, D &error, bool extrapolate_error=false)
void reinitialize(const D *data=0)
#define TA_USER_ASSERT(a, m)
void compute_extrapolation_parameters(const D &error, bool increase_iter=false)
const EigenVectorX & get_coeffs()
calling this function returns extrapolation coefficients
DistArray< Tile, Policy >::element_type dot_product(const DistArray< Tile, Policy > &a1, const DistArray< Tile, Policy > &a2)