19 {
20 double H0 =
m_optConfig.opts.lbfgs.inverse_curvature;
21 Eigen::VectorXd r =
m_objf->getPositions();
22
25
28 if (C < 0) {
29 QUILL_LOG_DEBUG(
30 m_log,
"[LBFGS] Negative curvature: {:.4f} eV/A^2 take max move step",
31 C);
34 }
35
38 QUILL_LOG_DEBUG(
m_log,
"[LBFGS] Curvature: {:.4e} eV/A^2", C);
39 }
40 }
41
44 eonc::safemath::safe_normalized(a_f));
45 Eigen::VectorXd dg =
m_objf->getGradient(
true) + a_f;
46 double C = dg.dot(eonc::safemath::safe_normalized(a_f)) /
50 if (H0 < 0) {
51 QUILL_LOG_WARNING(
m_log,
52 "[LBFGS] Negative curvature calculated via FD: {:.4e} "
53 "eV/A^2, take max move step",
54 C);
57 } else {
58 QUILL_LOG_DEBUG(
m_log,
59 "[LBFGS] Curvature calculated via FD: {:.4e} eV/A^2", C);
60 }
61 }
62
63 int loopmax =
m_s.size();
64 std::vector<double> a(loopmax);
65
66 Eigen::VectorXd q = -a_f;
67
68 for (int i = loopmax - 1; i >= 0; i--) {
71 }
72
73 Eigen::VectorXd z = H0 * q;
74
75 for (int i = 0; i < loopmax; i++) {
77 z +=
m_s[i] * (a[i] - b);
78 }
79
80 Eigen::VectorXd d = -z;
81
83 if (distance >= a_maxMove &&
m_optConfig.opts.lbfgs.distance_reset) {
84 QUILL_LOG_DEBUG(
m_log,
85 "[LBFGS] reset memory, proposed step too large: {:.4f}",
86 distance);
89 }
90
91 double vd = eonc::safemath::safe_normalized(d).dot(
92 eonc::safemath::safe_normalized(a_f));
93 if (vd > 1.0)
94 vd = 1.0;
95 if (vd < -1.0)
96 vd = -1.0;
98 if (angle > 90.0 &&
m_optConfig.opts.lbfgs.angle_reset) {
99 QUILL_LOG_DEBUG(
m_log,
100 "[LBFGS] reset memory, angle between LBFGS angle and "
101 "force too large: {:.4f}",
102 angle);
105 }
106
108}
std::deque< double > m_rho
std::deque< Eigen::VectorXd > m_y
std::deque< Eigen::VectorXd > m_s
eonc::log::FileScoped m_log
const OptimizerConfig m_optConfig
std::shared_ptr< ObjectiveFunction > m_objf
VectorXd maxAtomMotionAppliedV(const VectorXd v1, double maxMotion)
double maxAtomMotionV(const VectorXd v1)
constexpr double safe_div(double num, double denom, double fallback=0.0)
double safe_acos(double x)
constexpr double safe_recip(double x, double fallback=0.0)