158 {
160 alignment = 0.0;
161
163 QUILL_LOG_WARNING(log, "Invalid climbing image for MMF: {}",
165 return -1;
166 }
167
171 } else {
173 }
174 double tangentNorm = initialMode.norm();
175 if (tangentNorm < 1e-8) {
176 QUILL_LOG_WARNING(log, "Tangent too small for MMF initialization");
177 return -1;
178 }
179 initialMode /= tangentNorm;
180
181 auto tempMinModeSearch = std::make_shared<MinModeSaddleSearch>(
184
185 int minModeStatus;
186 try {
187 minModeStatus = tempMinModeSearch->run(
cfg_.max_steps);
188 } catch (const eonc::DimerModeRestoredException &) {
190 QUILL_LOG_DEBUG(log, "MMF: Dimer restored to best state");
191 } catch (const eonc::DimerModeLostException &) {
193 QUILL_LOG_WARNING(log, "Dimer lost mode during MMF refinement");
194 }
195
197
198 double eigenvalue = tempMinModeSearch->getEigenvalue();
199 if (eigenvalue > 0.0) {
200 QUILL_LOG_WARNING(log,
201 "MMF skipped: Positive curvature detected (eig={:.4f}).",
202 eigenvalue);
203 return -2;
204 }
205
206 AtomMatrix finalModeMatrix = tempMinModeSearch->getEigenvector();
207 VectorXd finalMode =
208 VectorXd::Map(finalModeMatrix.data(), finalModeMatrix.size());
209 VectorXd currentTangent =
212 if (finalMode.size() != currentTangent.size()) {
213 QUILL_LOG_WARNING(log,
214 "MMF mode size {} != tangent size {}; skip alignment",
215 finalMode.size(), currentTangent.size());
216 alignment = 0.0;
217 } else if (finalMode.norm() == 0.0 || currentTangent.norm() == 0.0) {
218 alignment = 0.0;
219 } else {
220 alignment =
221 std::abs(finalMode.normalized().dot(currentTangent.normalized()));
222 }
223
226 if (alignment <
cfg_.angle_tol) {
227 QUILL_LOG_WARNING(
228 log,
229 "MMF converged/restored but mode drifted (alignment={:.3f} < {:.3f})",
230 alignment,
cfg_.angle_tol);
231 return -1;
232 }
235 return 0;
237 return 1;
238 } else {
239 QUILL_LOG_WARNING(log, "MMF failed. Mode-tangent alignment: {:.3f}",
240 alignment);
241 return -1;
242 }
243}
@ STATUS_BAD_MAX_ITERATIONS
@ STATUS_DIMER_RESTORED_BEST
std::vector< std::shared_ptr< AtomMatrix > > tangent
std::shared_ptr< Potential > pot