51 const VectorXi &mobileIn) {
54 lowestEv.resize(matter->numberOfAtoms(), 3);
58 const int size = 3 *
static_cast<int>(mobile.size());
64 const long maxIters = std::max(1L,
params.lanczos_options().max_iterations);
65 MatrixXd T(size, maxIters), Q(size, maxIters);
69 double alpha, beta = r.norm();
74 double ew = 0, ewOld = 0, ewAbsRelErr;
75 const double dr =
params.main_options().finiteDifference;
81 VectorXd evEst, evT, evOldEst;
83 auto tmpMatter = std::make_unique<Matter>(*matter);
84 const long forceCallsStart = tmpMatter->getForceCalls();
85 const AtomMatrix pos0 = matter->getPositions();
86 const VectorXd force0 =
mobileForces(tmpMatter.get(), mobile);
88 auto applyH = [&](
const VectorXd &v) -> VectorXd {
89 auto at = [&](
double scale) -> VectorXd {
93 tmpMatter->setPositions(pos);
99 for (
int i = 0; i < size; i++) {
103 u = applyH(Q.col(i));
108 r = u - beta * Q.col(i - 1);
110 alpha = Q.col(i).dot(r);
111 r = r - alpha * Q.col(i);
122 const bool krylovClosed = beta <= 1e-10 * std::fabs(alpha);
125 Eigen::SelfAdjointEigenSolver<MatrixXd> es(T.block(0, 0, i + 1, i + 1));
126 ew = es.eigenvalues()(0);
127 evT = es.eigenvectors().col(0);
129 std::fabs(ewOld), 1.0);
132 evEst = Q.block(0, 0, size, i + 1) * evT;
133 eonc::safemath::safe_normalize_inplace(evEst);
139 "[ILanczos] {:9s} {:9s} {:10s} {:14s} {:9.4f} "
140 "{:10.6f} {:7.3f} {:5} n_mobile={}",
141 "----",
"----",
"----",
"----", ew, ewAbsRelErr,
144 QUILL_LOG_ERROR(
log,
"[ILanczos] ERROR: linear dependence");
147 if (ewAbsRelErr <
params.lanczos_options().tolerance) {
148 QUILL_LOG_INFO(
log,
"[ILanczos] Tolerance reached: {}",
149 params.lanczos_options().tolerance);
158 QUILL_LOG_ERROR(
log,
"[ILanczos] ERROR: linear dependence");
163 double Cnew = u.dot(Q.col(i));
165 std::fabs(Cprev), 1.0);
166 if (ewAbsRelErr <=
params.lanczos_options().tolerance) {
169 QUILL_LOG_INFO(
log,
"[ILanczos] Tolerance reached: {}",
170 params.lanczos_options().tolerance);
176 if (i >=
params.lanczos_options().max_iterations - 1) {
177 QUILL_LOG_ERROR(
log,
"[ILanczos] Max iterations");
186 if (evEst.size() == size) {
VectorXd fdHessianVector(FdScheme scheme, double dr, const VectorXd &force0, Eval &&eval)
Energy Hessian-vector product -dF.
void unpackMobileRows(const VectorXd &packed, const VectorXi &mobile, AtomMatrix &full)
Write a 3*n_mobile vector into full AtomMatrix rows (other rows unchanged).