25 VectorXd min1Freqs, saddleFreqs, min2Freqs;
34 atoms =
movedAtoms(parameters, min1, saddle, min2);
37 assert(atoms.rows() > 0);
40 Hessian hessian(parameters, min1);
41 min1Freqs = hessian.
getFreqs(min1, atoms);
42 if (min1Freqs.size() == 0) {
52 saddleFreqs = hessian.
getFreqs(saddle, atoms);
53 if (saddleFreqs.size() == 0) {
63 min2Freqs = hessian.
getFreqs(min2, atoms);
64 if (min2Freqs.size() == 0) {
77 if ((min1Freqs.size() != saddleFreqs.size()) ||
78 (min2Freqs.size() != saddleFreqs.size())) {
80 EONC_LOG_ERROR(
"[Prefactor] Bad prefactor: Hessian sizes do not match");
94 for (
int i = 0; i < min1Freqs.size(); i++) {
95 if (min1Freqs(i) < 0) {
96 EONC_LOG_DEBUG(
"[Prefactor] min1 had negative mode of {}", min1Freqs(i));
100 if (numNegFreq != 0) {
101 EONC_LOG_DEBUG(
"[Prefactor] Error: {} negative modes at min1", numNegFreq);
106 for (
int i = 0; i < saddleFreqs.size(); i++) {
107 if (saddleFreqs(i) < 0) {
111 if (numNegFreq != 1) {
117 for (
int i = 0; i < min2Freqs.size(); i++) {
118 if (min2Freqs(i) < 0) {
122 if (numNegFreq != 0) {
134 for (
int i = 0; i < saddleFreqs.size(); i++) {
135 pref1 *= min1Freqs[i];
136 pref2 *= min2Freqs[i];
137 if (saddleFreqs[i] > 0) {
138 pref1 /= saddleFreqs[i];
139 pref2 /= saddleFreqs[i];
147 double h_bar = 6.582119e-16;
148 double h = 4.135667e-15;
149 double temp = (h_bar / (2.0 * kB_T));
151 for (
int i = 0; i < min1Freqs.size(); i++) {
152 pref1 = pref1 * (std::sinh(temp * (std::sqrt(min1Freqs[i]) / 10.18e-15)));
153 pref2 = pref2 * (std::sinh(temp * (std::sqrt(min2Freqs[i]) / 10.18e-15)));
155 if (saddleFreqs[i] > 0) {
157 pref1 / (std::sinh(temp * (std::sqrt(saddleFreqs[i]) / 10.18e-15)));
159 pref2 / (std::sinh(temp * (std::sqrt(saddleFreqs[i]) / 10.18e-15)));
162 pref1 = 2. * kB_T / (h)*pref1;
163 pref2 = 2. * kB_T / (h)*pref2;
165 EONC_LOG_DEBUG(
"[Prefactor] reactant to product prefactor: {:.3e}", pref1);
166 EONC_LOG_DEBUG(
"[Prefactor] product to reactant prefactor: {:.3e}", pref2);
171 std::ofstream outFile(
"freqs.dat", std::ios::app);
172 if (!outFile.is_open())
175 outFile << std::format(
"[Prefactor] Frequencies at {}\n", name);
176 for (
int i = 0; i < freqs.size(); i++) {
177 outFile <<
"\n" << std::format(
"{:10.6f} ", freqs(i));
178 if ((i + 1) % 5 == 0) {
189 VectorXi moved(nAtoms);
190 moved.setConstant(-1);
197 diffMin1.array() *= saddle->
getFree().array();
198 diffMin2.array() *= saddle->
getFree().array();
201 for (
int i = 0; i < nAtoms; i++) {
202 if ((diffMin1.row(i).norm() >
204 (diffMin2.row(i).norm() >
208 if (std::find(moved.data(), moved.data() + nMoved, i) ==
209 moved.data() + nMoved) {
213 for (
int j = 0; j < nAtoms; j++) {
214 double diffRSaddle = saddle->
distance(i, j);
218 if (std::find(moved.data(), moved.data() + nMoved, j) ==
219 moved.data() + nMoved) {
227 return moved.head(nMoved);
236 VectorXi moved(nAtoms);
237 moved.setConstant(-1);
244 diffMin1.array() *= saddle->
getFree().array();
245 diffMin2.array() *= saddle->
getFree().array();
247 VectorXd diff(nAtoms);
248 diff.setConstant(0.0);
252 "[Prefactor] including all atoms that make up {:.3f}% of the motion",
256 for (
int i = 0; i < nAtoms; i++) {
257 diff[i] = std::max(diffMin1.row(i).norm(), diffMin2.row(i).norm());
259 if (diff[i] <= diff[mini]) {
264 EONC_LOG_DEBUG(
"[Prefactor] sum of atom distances moved {:.4f}", sum);
273 for (
int i = 0; i < nAtoms; i++) {
274 if (diff[i] >= diff[maxi]) {
275 if (std::find(moved.data(), moved.data() + nMoved, i) ==
276 moved.data() + nMoved) {
281 moved[nMoved] = maxi;
286 int totalAtoms = nMoved;
287 for (
int i = 0; i < nMoved; i++) {
288 for (
int j = 0; j < nAtoms; j++) {
292 double diffRSaddle = saddle->
distance(moved[i], j);
297 if (std::find(moved.data(), moved.data() + totalAtoms, j) ==
298 moved.data() + totalAtoms) {
299 moved[totalAtoms++] = j;
304 EONC_LOG_DEBUG(
"[Prefactor] including {} atoms in the hessian ({} moved + {} "
306 totalAtoms, nMoved, totalAtoms - nMoved);
307 return moved.head(totalAtoms);
313 VectorXi moved(nAtoms);
314 moved.setConstant(-1);
317 for (
int i = 0; i < nAtoms; i++) {
323 return moved.head(nMoved);
Eigen::Matrix< double, Eigen::Dynamic, 3, eOnStorageOrder > AtomMatrix
#define EONC_LOG_DEBUG(...)
#define EONC_LOG_ERROR(...)
VectorXd removeZeroFreqs(const VectorXd &freqs)
VectorXd getFreqs(Matter *matterIn, const VectorXi &atomsIn)
double distance(long index1, long index2) const
AtomMatrix getFree() const
AtomMatrix pbc(const AtomMatrix &diff) const
long int numberOfAtoms() const
long int numberOfFreeAtoms() const
const AtomMatrix & getPositions() const
int getFixed(long int atom) const
1 if every Cartesian axis of the atom is fixed, else 0.
struct eonc::Parameters::structure_comparison_options_t structure_comparison_options
struct eonc::Parameters::prefactor_options_t prefactor_options
struct eonc::Parameters::main_options_t main_options
void logFreqs(const VectorXd &freqs, const char *name)
VectorXi allFreeAtoms(Matter *matter)
VectorXi movedAtomsPct(const Parameters ¶meters, Matter *min1, Matter *saddle, Matter *min2)
VectorXi movedAtoms(const Parameters ¶meters, Matter *min1, Matter *saddle, Matter *min2)
int getPrefactors(const Parameters ¶meters, Matter *min1, Matter *saddle, Matter *min2, double &pref1, double &pref2)
const char FILTER_FRACTION[]
quill::Logger * get() noexcept
Get or create the default "combi" logger.
std::string filter_scheme