Loading...
Searching...
No Matches
SafeHyperJob.cpp
Go to the documentation of this file.
1/*
2** This file is part of eOn.
3**
4** SPDX-License-Identifier: BSD-3-Clause
5**
6** Copyright (c) 2010--present, eOn Development Team
7** All rights reserved.
8**
9** Repo:
10** https://github.com/TheochemUI/eOn
11*/
12#include "eon/SafeHyperJob.h"
13#include "eon/BondBoost.h"
14#include "eon/Dynamics.h"
15#include "eon/ForceCallTimer.h"
16
17#include <cmath>
18
20 if (newStateFlag) {
21 QUILL_LOG_DEBUG(log, "Transition time: {:.2e} s",
22 minCorrectedTime * 1.0e-15 * params.constants.timeUnit);
23 } else {
24 QUILL_LOG_DEBUG(log,
25 "No new state was found in {} dynamics steps ({:.3e} s)",
26 params.dynamics_options.steps,
27 time * 1.0e-15 * params.constants.timeUnit);
28 }
29}
30
32 bool transitionFlag = false, recordFlag = true, stopFlag = false,
33 firstTransitFlag = false;
34 long nFreeCoord = reactant->numberOfFreeAtoms() * 3;
35 long mdBufferLength;
36 long step = 0, refineStep, newStateStep = 0;
37 long nCheck = 0, nRecord = 0, nBoost = 0, nState = 0;
38 long StateCheckInterval, RecordInterval;
39 double kinE, kinT, avgT, varT;
40 double kB = params.constants.kB;
41 double correctedTime = 0.0, sumCorrectedTime = 0.0, firstTransitionTime = 0.0;
42 double Temp = 0.0, sumT = 0.0, sumT2 = 0.0;
43 double sumboost = 0.0, boost = 1.0, boostPotential = 0.0;
44 double transitionTime_current = 0.0, transitionTime_pre = 0.0;
45 AtomMatrix velocity;
46
47 minCorrectedTime = 1.0e200;
48 StateCheckInterval =
49 static_cast<long>(params.parallel_replica_options.state_check_interval /
50 params.dynamics_options.time_step);
51 RecordInterval =
52 static_cast<long>(params.parallel_replica_options.record_interval /
53 params.dynamics_options.time_step);
54 Temp = params.main_options.temperature;
56
57 mdBufferLength = static_cast<long>(StateCheckInterval / RecordInterval);
58 std::vector<std::shared_ptr<Matter>> mdBuffer(mdBufferLength);
59 for (long i = 0; i < mdBufferLength; i++) {
60 mdBuffer[i] = std::make_shared<Matter>(pot, params);
61 }
62 timeBuffer.resize(mdBufferLength);
63 biasBuffer.resize(mdBufferLength);
64
65 Dynamics safeHyper(current.get(), params);
66 BondBoost bondBoost(current.get(), params);
67
68 if (params.hyperdynamics_options.bias_potential ==
70 bondBoost.initialize();
71 }
72
73 safeHyper.setThermalVelocity();
74
75 {
77 dephase();
78 }
79
80 QUILL_LOG_DEBUG(
81 log,
82 "Starting MD run\nTemperature: {:.2f} Kelvin\n"
83 "Total Simulation Time: {:.2f} fs\nTime Step: {:.2f} fs\nTotal Steps: {}",
84 Temp,
85 params.dynamics_options.steps * params.dynamics_options.time_step *
86 params.constants.timeUnit,
87 params.dynamics_options.time_step * params.constants.timeUnit,
88 params.dynamics_options.steps);
89 QUILL_LOG_DEBUG(log, "MD buffer length: {}", mdBufferLength);
90
91 long tenthSteps = params.dynamics_options.steps / 10;
92 if (tenthSteps == 0) {
93 tenthSteps = params.dynamics_options.steps;
94 }
95
96 while (!stopFlag) {
97 if ((params.hyperdynamics_options.bias_potential ==
99 !newStateFlag) {
100 bondBoost.advance();
101 boostPotential = bondBoost.boost();
102 QUILL_LOG_TRACE_L1(log, "step= {} , boost = {:.5f}", step,
103 boostPotential);
104 boost = std::exp(boostPotential / kB / Temp);
105 time += params.dynamics_options.time_step * boost;
106 if (boost > 1.0) {
107 sumboost += boost;
108 nBoost++;
109 }
110 }
111
112 kinE = current->getKineticEnergy();
113 kinT = (2.0 * kinE / nFreeCoord / kB);
114 sumT += kinT;
115 sumT2 += kinT * kinT;
116 QUILL_LOG_TRACE_L1(log, "steps = {:10} temp = {:10.5f}", step, kinT);
117
118 safeHyper.oneStep();
119 mdFCalls++;
120
121 nCheck++;
122 step++;
123 QUILL_LOG_TRACE_L1(log, "step = {:4}, time = {:10.4f}", step, time);
124
125 if (params.parallel_replica_options.refine_transition && recordFlag &&
126 !newStateFlag) {
127 if (nCheck % RecordInterval == 0) {
128 *mdBuffer[nRecord] = *current;
129 timeBuffer[nRecord] = time;
130 biasBuffer[nRecord] = boostPotential;
131 nRecord++;
132 }
133 }
134
135 if ((nCheck == StateCheckInterval) && !newStateFlag) {
136 nCheck = 0;
137 nRecord = 0;
138 {
140 transitionFlag = checkState(current.get(), reactant.get());
141 }
142 if (transitionFlag) {
143 nState++;
144 QUILL_LOG_DEBUG(log, "New State {}: ", nState);
147 newStateStep = step;
148 transitionStep = newStateStep;
149 firstTransitFlag = 1;
150 }
151 }
152
153 if (transitionFlag) {
154 QUILL_LOG_TRACE_L1(log, "Refining transition time.");
155 {
157 refineStep = refine(mdBuffer, reactant.get());
158 }
159
161 newStateStep - StateCheckInterval + refineStep * RecordInterval;
162 transitionTime_current = timeBuffer[refineStep];
163 transitionTime = transitionTime_current - transitionTime_pre;
164 transitionTime_pre = transitionTime_current;
165 transitionPot = biasBuffer[refineStep];
166 correctedTime =
167 transitionTime * std::exp((-1) * transitionPot / kB / Temp);
168 sumCorrectedTime += correctedTime;
169 if (nState == 1) {
170 firstTransitionTime = transitionTime;
171 }
172
173 *current = *mdBuffer[refineStep - 1];
174 velocity = current->getVelocities();
175 velocity = velocity * (-1);
176 current->setVelocities(velocity);
177
178 if (correctedTime < minCorrectedTime) {
179 minCorrectedTime = correctedTime;
180 *saddle = *mdBuffer[refineStep];
182 }
183 QUILL_LOG_DEBUG(log,
184 "tranisitonTime= {:.3e} s, biasPot= {:.3f} eV, "
185 "correctedTime= {:.3e} s, "
186 "sumCorrectedTime= {:.3e} s, minCorTime= {:.3e} s",
187 transitionTime * 1e-15 * params.constants.timeUnit,
189 correctedTime * 1e-15 * params.constants.timeUnit,
190 sumCorrectedTime * 1e-15 * params.constants.timeUnit,
191 minCorrectedTime * 1.0e-15 * params.constants.timeUnit);
192
193 transitionFlag = false;
194 }
195
196 if (firstTransitFlag && sumCorrectedTime > firstTransitionTime) {
197 stopFlag = true;
198 newStateFlag = true;
199 }
200
201 if ((step % tenthSteps == 0) || (step == params.dynamics_options.steps)) {
202 double maxAtomDistance = current->perAtomNorm(*reactant);
203 QUILL_LOG_DEBUG(
204 log, "progress: {:.0f}%, max displacement: {:.3f}, step {} / {}",
205 static_cast<double>(100.0 * step / params.dynamics_options.steps),
206 maxAtomDistance, step, params.dynamics_options.steps);
207 }
208
209 // Honor dynamics step budget (parity with TADJob); without this the
210 // loop only exits on a confidence-gated transition and can run forever.
211 if (step >= params.dynamics_options.steps) {
212 stopFlag = true;
213 }
214 }
215
216 avgT = sumT / step;
217 varT = sumT2 / step - avgT * avgT;
218
219 if (nBoost > 0) {
220 QUILL_LOG_DEBUG(log,
221 "Temperature : Average = {:.6f} ; Stddev = {:.6f} ; "
222 "Factor = {:.6f}; Boost = {:.6f}",
223 avgT, std::sqrt(varT), varT / avgT / avgT * nFreeCoord / 2,
224 sumboost / nBoost);
225 } else {
226 QUILL_LOG_DEBUG(
227 log,
228 "Temperature : Average = {:.6f} ; Stddev = {:.6f} ; Factor = {:.6f}",
229 avgT, std::sqrt(varT), varT / avgT / avgT * nFreeCoord / 2);
230 }
231 if (std::isfinite(avgT) == 0) {
232 QUILL_LOG_DEBUG(log, "Infinite average temperature, something went wrong!");
233 newStateFlag = false;
234 }
235
236 // finalState is only filled on transition; keep product valid otherwise.
237 if (newStateFlag && finalState) {
239 } else if (current) {
240 *product = *current;
241 }
242
243 if (newStateFlag) {
244 return 1;
245 } else {
246 return 0;
247 }
248}
Eigen::Matrix< double, Eigen::Dynamic, 3, eOnStorageOrder > AtomMatrix
Definition Eigen.h:37
void reportResults() override
Post-dynamics logging (override for job-specific messages).
Functionality relying on the conjugate gradients algorithm.
Definition BondBoost.h:25
double boost()
Evaluate the current bias potential and write bias forces.
void advance()
Advance the equilibration / boost schedule by one MD step.
Definition BondBoost.cpp:92
void oneStep(int stepNumber=-1)
Definition Dynamics.cpp:41
void setThermalVelocity()
Definition Dynamics.cpp:160
RAII wrapper for tracking force calls over a scope.
static const char BOND_BOOST[]
Definition BondBoost.h:77
Parameters params
Definition Job.h:54
void dephase()
Dephase the trajectory to ensure thermal independence.
std::shared_ptr< Matter > saddle
std::shared_ptr< Matter > product
long refine(const std::vector< std::shared_ptr< Matter > > &buff, Matter *reactant)
Binary search for the transition frame in a snapshot buffer.
std::shared_ptr< Matter > finalState
std::shared_ptr< Matter > reactant
std::shared_ptr< Matter > current
bool checkState(Matter *current, Matter *reactant)
Minimize a copy of current and compare to reactant.
std::shared_ptr< Matter > finalStateTmp
int dynamics() override
The accelerated dynamics loop. Returns status (1 = transition, 0 = none).
std::vector< double > timeBuffer
std::vector< double > biasBuffer