113 {
114 int nAtoms =
matter->numberOfAtoms();
115
116 int size =
static_cast<int>(
atoms.rows()) * 3;
117 QUILL_LOG_DEBUG(
log,
"[Hessian] Hessian size: {}\n", size);
118 if (size == 0) {
119 return false;
120 }
121
122
123 for (
int a = 0; a <
atoms.rows(); ++a) {
124 const long idx =
atoms(a);
125 if (idx < 0 || idx >= nAtoms) {
127 "[Hessian] atom index {} out of range [0, {}) at list "
128 "entry {}; aborting FD Hessian",
129 idx, nAtoms, a);
130 return false;
131 }
132 }
133
134 Matter matterTemp(*
matter);
135 double dr =
parameters.main_options.finiteDifference;
136 if (!(dr > 0.0) || !std::isfinite(dr)) {
137 QUILL_LOG_ERROR(
log,
"[Hessian] invalid finiteDifference dr={}\n", dr);
138 return false;
139 }
140
141 const bool useCentral = isCentralScheme(
parameters.hessian_options.fd_scheme);
142 const std::string &ckptPath =
parameters.hessian_options.checkpoint_path;
143 const bool wantResume =
144 parameters.hessian_options.resume && !ckptPath.empty();
145
152
155
156 int startCol = 0;
157 if (wantResume && loadColumnCheckpoint(ckptPath, size, startCol,
hessian)) {
158 QUILL_LOG_DEBUG(
log,
"[Hessian] resume from column {} / {}\n", startCol,
159 size);
160 } else {
161 startCol = 0;
163 }
164
165 force0 = matterTemp.getForces();
166 if (!force0.allFinite()) {
167 QUILL_LOG_ERROR(
log,
"[Hessian] non-finite forces at undisplaced geometry; "
168 "aborting FD Hessian");
169 return false;
170 }
171
172 for (int i = startCol; i < size; i++) {
173 posDisplace.setZero();
174 posDisplace(
atoms(i / 3), i % 3) = dr;
175
176 posTemp = pos + posDisplace;
177 matterTemp.setPositions(posTemp);
178 forcePlus = matterTemp.getForces();
179 if (!forcePlus.allFinite()) {
181 "[Hessian] non-finite forces for FD column {} (+); "
182 "aborting FD Hessian",
183 i);
184 return false;
185 }
186
187 if (useCentral) {
188 posTemp = pos - posDisplace;
189 matterTemp.setPositions(posTemp);
190 forceMinus = matterTemp.getForces();
191 if (!forceMinus.allFinite()) {
193 "[Hessian] non-finite forces for FD column {} (-); "
194 "aborting FD Hessian",
195 i);
196 return false;
197 }
198
199 for (int j = 0; j < size; j++) {
200 const double dF =
201 forcePlus(
atoms(j / 3), j % 3) - forceMinus(
atoms(j / 3), j % 3);
202 hessian(i, j) = -dF / (2.0 * dr);
203 const double effMass = std::sqrt(
matter->getMass(
atoms(j / 3)) *
206 }
207 } else {
208
209 for (int j = 0; j < size; j++) {
210 const double dF =
211 forcePlus(
atoms(j / 3), j % 3) - force0(
atoms(j / 3), j % 3);
213 const double effMass = std::sqrt(
matter->getMass(
atoms(j / 3)) *
216 }
217 }
218
219 if (!ckptPath.empty()) {
220
221 saveColumnCheckpoint(ckptPath, size, i + 1,
hessian);
222 }
223 }
224
225
226 for (int i = 0; i < size; i++) {
227 for (int j = 0; j < i; j++) {
230 }
231 }
232
234 QUILL_LOG_ERROR(
log,
"[Hessian] non-finite entries after FD assembly; "
235 "aborting eigen solve");
236 return false;
237 }
238
240 QUILL_LOG_DEBUG(
log,
"[Hessian] writing hessian\n");
241 std::ofstream hessfile;
242 hessfile.open("hessian.dat");
244 hessfile.close();
245 }
246
247
248 if (!ckptPath.empty()) {
249 std::remove(ckptPath.c_str());
250 }
251
252 double t0, t1;
254 QUILL_LOG_DEBUG(
log,
"[Hessian] calculating eigen values of the hessian\n");
255
256 using ColMajorXd =
257 Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic, Eigen::ColMajor>;
258 ColMajorXd hessianCol =
hessian;
259 Eigen::SelfAdjointEigenSolver<ColMajorXd> es(hessianCol,
260 Eigen::EigenvaluesOnly);
262 QUILL_LOG_DEBUG(
log,
"[Hessian] eigenvalue problem took {:.4e} seconds\n",
263 t1 - t0);
264 if (es.info() != Eigen::Success) {
266 "[Hessian] SelfAdjointEigenSolver failed (info={}); "
267 "aborting",
268 static_cast<int>(es.info()));
269 return false;
270 }
271 freqs = es.eigenvalues();
272 if (!
freqs.allFinite()) {
273 QUILL_LOG_ERROR(
log,
"[Hessian] non-finite eigenvalues; aborting");
274 return false;
275 }
276
277 return true;
278}
Eigen::Matrix< double, Eigen::Dynamic, 3, eOnStorageOrder > AtomMatrix
void getTime(double *real, double *user, double *sys)
constexpr double safe_div(double num, double denom, double fallback=0.0)