24 std::vector<std::shared_ptr<Matter>> mdSnapshots;
25 std::vector<double> mdTimes;
26 QUILL_LOG_DEBUG(
log,
"Starting dynamics NEB saddle search");
28 if (std::filesystem::exists(
"masses.dat")) {
29 QUILL_LOG_DEBUG(
log,
"Found mass weights file");
30 Eigen::VectorXd masses =
33 QUILL_LOG_DEBUG(
log,
"Applied mass weights");
35 QUILL_LOG_DEBUG(
log,
"No mass weights file found");
40 log,
"Initializing velocities from Maxwell-Boltzmann distribution");
45 static_cast<int>(std::floor(
params.parallel_replica_options.dephase_time /
46 params.dynamics_options.time_step +
51 QUILL_LOG_DEBUG(
log,
"Dephasing: {} steps", dephaseSteps);
57 for (
int step = 1; step <= dephaseSteps; step++) {
67 QUILL_LOG_DEBUG(
log,
"Dephasing successful");
70 QUILL_LOG_DEBUG(
log,
"Transition occured during dephasing; Restarting");
78 if (
params.hyperdynamics_options.bias_potential ==
80 QUILL_LOG_DEBUG(
log,
"Initializing Bond Boost");
84 int checkInterval =
static_cast<int>(
85 params.saddle_search_options.dynamics.state_check_interval /
86 params.dynamics_options.time_step +
89 static_cast<int>(
params.saddle_search_options.dynamics.record_interval /
90 params.dynamics_options.time_step +
93 if (
params.debug_options.write_movies) {
95 QUILL_LOG_WARNING(
log,
"Failed to write dynamics movie header");
99 for (
int step = 1; step <=
params.dynamics_options.steps; step++) {
102 if (recordInterval != 0 && step % recordInterval == 0) {
104 log,
"recording configuration at step {} time {:.3f}", step,
105 step *
params.dynamics_options.time_step *
params.constants.timeUnit);
107 auto snapshot = std::make_shared<Matter>(*
saddle);
108 mdSnapshots.push_back(snapshot);
109 mdTimes.push_back(step *
params.dynamics_options.time_step);
112 if (
params.debug_options.write_movies) {
114 QUILL_LOG_WARNING(
log,
"Failed to append dynamics movie frame");
118 if (step % checkInterval == 0) {
119 QUILL_LOG_DEBUG(
log,
"Minimizing trajectory, step {}", step);
125 QUILL_LOG_DEBUG(
log,
"Found new state");
127 *
saddle = *mdSnapshots[image];
128 QUILL_LOG_DEBUG(
log,
"Found transition at snapshot image {}", image);
129 for (
int ii = 0; ii < static_cast<int>(mdTimes.size()); ii++) {
130 QUILL_LOG_DEBUG(
log,
"MDTimes[{}] = {:.3f}", ii,
131 mdTimes[ii] *
params.constants.timeUnit);
134 time = mdTimes[image] -
135 params.saddle_search_options.dynamics.record_interval / 2.0;
136 QUILL_LOG_DEBUG(
log,
"Transition time {:.2f} fs",
141 if (!
params.saddle_search_options.dynamics.linear_interpolation) {
143 log,
"Interpolating initial band through MD transition state");
148 QUILL_LOG_DEBUG(
log,
"Initial band saved to neb_initial_band.con");
150 neb.path[0]->matter2con(
"neb_initial_band.con",
false))) {
151 QUILL_LOG_WARNING(
log,
"Failed to write neb_initial_band.con");
153 int mid =
neb.numImages / 2 + 1;
154 for (
int img = 1; img <=
neb.numImages; img++) {
156 double frac =
static_cast<double>(img) /
static_cast<double>(mid);
157 neb.path[img]->setPositions(
reactant->getPositions() +
158 frac * reactantToSaddle);
159 }
else if (img > mid) {
160 double frac =
static_cast<double>(img - mid) /
161 static_cast<double>(
neb.numImages - mid + 1);
162 neb.path[img]->setPositions(
saddle->getPositions() +
163 frac * saddleToProduct);
165 neb.path[img]->setPositions(
saddle->getPositions());
168 neb.path[img]->matter2con(
"neb_initial_band.con",
true))) {
169 QUILL_LOG_WARNING(
log,
"Failed to append neb_initial_band frame");
173 "neb_initial_band.con",
true))) {
174 QUILL_LOG_WARNING(
log,
175 "Failed to append neb_initial_band endpoint");
179 log,
"Linear interpolation between minima used for initial band");
181 neb.path[0]->matter2con(
"neb_initial_band.con",
false))) {
182 QUILL_LOG_WARNING(
log,
"Failed to write neb_initial_band.con");
184 for (
int j = 1; j <=
neb.numImages + 1; j++) {
186 neb.path[j]->matter2con(
"neb_initial_band.con",
true))) {
187 QUILL_LOG_WARNING(
log,
"Failed to append neb_initial_band frame");
193 if (
params.neb_options.max_iterations > 0) {
198 neb.printImageData(
true);
199 int extremumImage = -1;
201 for (jExt = 0; jExt <
neb.numExtrema; jExt++) {
202 if (
neb.extremumCurvature[jExt] <
203 params.saddle_search_options.dynamics.max_init_curvature) {
205 static_cast<int>(std::floor(
neb.extremumPosition[jExt]));
207 double interpDist =
neb.extremumPosition[jExt] -
208 static_cast<double>(extremumImage);
210 saddle->pbc(
neb.path[extremumImage + 1]->getPositions() -
211 neb.path[extremumImage]->getPositions());
212 saddle->setPositions(interpDist * bandDir +
214 mode =
saddle->pbc(
neb.path[extremumImage + 1]->getPositions() -
219 QUILL_LOG_DEBUG(
log,
"extrema #{} has eigenvalue {:.8f}",
224 log,
"chose image {} (extrema #{}) as extremum image",
225 extremumImage, jExt + 1);
233 if (extremumImage != -1) {
236 neb.extremumPosition[jExt] -
static_cast<double>(extremumImage);
237 QUILL_LOG_DEBUG(
log,
"interpDistance {}", interpDist);
239 saddle->pbc(
neb.path[extremumImage + 1]->getPositions() -
240 neb.path[extremumImage]->getPositions());
241 saddle->setPositions(interpDist * bandDir +
saddle->getPositions());
242 mode =
saddle->pbc(
neb.path[extremumImage + 1]->getPositions() -
247 log,
"no maxima found, using max energy non-endpoint image");
248 double maxEnergy = -std::numeric_limits<double>::infinity();
249 for (
int img = 1; img <=
neb.numImages; img++) {
250 double U =
neb.path[img]->getPotentialEnergy();
254 mode =
saddle->pbc(
neb.path[img + 1]->getPositions() -
259 if (maxEnergy <= reactant->getPotentialEnergy()) {
260 QUILL_LOG_DEBUG(
log,
"warning: no barrier found");
265 neb.maxEnergyImage =
neb.numImages / 2 + 1;
269 log,
"Initial saddle guess saved to saddle_initial_guess.con");
271 QUILL_LOG_WARNING(
log,
"Failed to write saddle_initial_guess.con");
275 int minModeStatus = search.
run();
278 QUILL_LOG_DEBUG(
log,
"error in min mode saddle search");
279 return minModeStatus;
288 QUILL_LOG_DEBUG(
log,
"found barrier of {:.3f}", barrier);
293 QUILL_LOG_DEBUG(
log,
"Still in original state");
bool relax(bool quiet=false, bool writeMovie=false, bool checkpoint=false, std::string prefixMovie=std::string(), std::string prefixCheckpoint=std::string(), bool retainMovieFrames=false)