51 {
53
56
58 if (dimer && !dimer->rotationDidConverge) {
59 if (dimer->getEigenvalue() < 0.0) {
62 "[MinMode] Dimer restored to best state with C_tau={:.4f}",
63 dimer->getEigenvalue());
64 throw eonc::DimerModeRestoredException();
65 } else {
66 throw eonc::DimerModeLostException();
67 }
68 }
70 }
71
74
77
78 if (eigenvalue > 0.0) {
79 if (
params.saddle_search_options.perp_force_ratio > 0.0) {
80 double d =
params.saddle_search_options.perp_force_ratio;
81 force = d * force - (1.0 + d) * proj;
82 }
else if (
params.saddle_search_options.confine_positive.enabled) {
83 if (
params.saddle_search_options.confine_positive.bowl_breakout) {
85 int nBowlActive =
86 params.saddle_search_options.confine_positive.bowl_active;
87 std::vector<int> indices_max(nBowlActive);
88
89
90 for (int j = 0; j < nBowlActive; j++) {
91 double f_max = forceTemp.row(0).norm();
92 int i_max = 0;
93 for (
long i = 0; i <
matter->numberOfAtoms(); i++) {
94 if (f_max < forceTemp.row(i).norm()) {
95 f_max = forceTemp.row(i).norm();
96 i_max = static_cast<int>(i);
97 }
98 }
99 forceTemp.row(i_max).setZero();
100 indices_max[j] = i_max;
101 }
102 forceTemp.setZero();
103 for (int j = 0; j < nBowlActive; j++) {
104 forceTemp.row(indices_max[j]) = -proj.row(indices_max[j]);
105 }
106 force = forceTemp;
107 } else {
108 int sufficientForce = 0;
109 double minForce =
110 params.saddle_search_options.confine_positive.min_force;
111 while (sufficientForce <
112 params.saddle_search_options.confine_positive.min_active) {
113 sufficientForce = 0;
114 force =
matter->getForces();
115 for (
long i = 0; i <
matter->numberOfAtoms(); i++) {
116 for (int k = 0; k < 3; k++) {
117 if (std::abs(force(i, k)) < minForce) {
118 force(i, k) = 0;
119 } else {
120 sufficientForce++;
121 force(i, k) =
122 -
params.saddle_search_options.confine_positive.boost *
123 proj(i, k);
124 }
125 }
126 }
127 minForce *=
128 params.saddle_search_options.confine_positive.scale_ratio;
129 }
130 }
131 } else {
132 force = -proj;
133 }
134 } else {
135 force += -2.0 * proj;
136 }
137
138 VectorXd forceV = VectorXd::Map(force.data(), 3 *
matter->numberOfAtoms());
139 return -forceV;
140 }
double matDot(const AtomMatrix &a, const AtomMatrix &b)
SIMD-optimized dot product for contiguous Eigen matrices.
Eigen::Matrix< double, Eigen::Dynamic, 3, eOnStorageOrder > AtomMatrix
#define EONC_LOG_DEBUG(...)
AtomMatrix eigenmodeGetEigenvector(EigenmodeStrategy &s)
Dispatch getEigenvector() to the active variant.
ImprovedDimer * asImprovedDimer(EigenmodeStrategy &s)
Access ImprovedDimer-specific features.
void eigenmodeCompute(EigenmodeStrategy &s, std::shared_ptr< Matter > matter, AtomMatrix direction)
Dispatch compute() to the active variant.
double eigenmodeGetEigenvalue(EigenmodeStrategy &s)
Dispatch getEigenvalue() to the active variant.