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
19namespace eonc {
20
22 if (newStateFlag) {
23 QUILL_LOG_DEBUG(log, "Transition time: {:.2e} s",
24 minCorrectedTime * 1.0e-15 * params.constants().timeUnit);
25 } else {
26 QUILL_LOG_DEBUG(log,
27 "No new state was found in {} dynamics steps ({:.3e} s)",
28 params.dynamics_options().steps,
29 time * 1.0e-15 * params.constants().timeUnit);
30 }
31}
32
34 bool transitionFlag = false, recordFlag = true, stopFlag = false,
35 firstTransitFlag = false;
36 long nFreeCoord = reactant->numberOfFreeAtoms() * 3;
37 long mdBufferLength;
38 long step = 0, refineStep, newStateStep = 0;
39 long nCheck = 0, nRecord = 0, nBoost = 0, nState = 0;
40 long StateCheckInterval, RecordInterval;
41 double kinE, kinT, avgT, varT;
42 double kB = params.constants().kB;
43 double correctedTime = 0.0, sumCorrectedTime = 0.0, firstTransitionTime = 0.0;
44 double Temp = 0.0, sumT = 0.0, sumT2 = 0.0;
45 double sumboost = 0.0, boost = 1.0, boostPotential = 0.0;
46 double transitionTime_current = 0.0, transitionTime_pre = 0.0;
47 AtomMatrix velocity;
48
49 minCorrectedTime = 1.0e200;
50 const auto clock = prdClock();
51 StateCheckInterval = clock.state_check;
52 RecordInterval = clock.record;
53 Temp = params.main_options().temperature;
55
56 mdBufferLength = clock.buffer;
57 std::vector<std::shared_ptr<Matter>> mdBuffer(mdBufferLength);
58 for (long i = 0; i < mdBufferLength; i++) {
59 mdBuffer[i] = std::make_shared<Matter>(pot, params);
60 }
61 timeBuffer.resize(mdBufferLength);
62 biasBuffer.resize(mdBufferLength);
63
64 Dynamics safeHyper(current.get(), params);
65 BondBoost bondBoost(current.get(), params);
66
67 if (params.hyperdynamics_options().bias_potential ==
69 bondBoost.initialize();
70 current->setBiasPotential(&bondBoost);
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 boost = 1.0;
98 boostPotential = 0.0;
99 if ((params.hyperdynamics_options().bias_potential ==
101 !newStateFlag) {
102 bondBoost.advance();
103 boostPotential = bondBoost.boost();
104 QUILL_LOG_TRACE_L1(log, "step= {} , boost = {:.5f}", step,
105 boostPotential);
106 if (Temp > 0.0 && kB > 0.0) {
107 boost = std::exp(boostPotential / kB / Temp);
108 } else {
109 boost = 1.0;
110 }
111 if (boost > 1.0) {
112 sumboost += boost;
113 nBoost++;
114 }
115 }
116 time += params.dynamics_options().time_step * boost;
117
118 kinE = current->getKineticEnergy();
119 kinT = (2.0 * kinE / nFreeCoord / kB);
120 sumT += kinT;
121 sumT2 += kinT * kinT;
122 QUILL_LOG_TRACE_L1(log, "steps = {:10} temp = {:10.5f}", step, kinT);
123
124 safeHyper.oneStep();
125 mdFCalls++;
126
127 nCheck++;
128 step++;
129 QUILL_LOG_TRACE_L1(log, "step = {:4}, time = {:10.4f}", step, time);
130
131 if (params.parallel_replica_options().refine_transition && recordFlag &&
132 !newStateFlag) {
133 if (nCheck % RecordInterval == 0) {
134 *mdBuffer[nRecord] = *current;
135 timeBuffer[nRecord] = time;
136 biasBuffer[nRecord] = boostPotential;
137 nRecord++;
138 }
139 }
140
141 if ((nCheck == StateCheckInterval) && !newStateFlag) {
142 nCheck = 0;
143 nRecord = 0;
144 {
146 transitionFlag = checkState(current.get(), reactant.get());
147 }
148 if (transitionFlag) {
149 nState++;
150 QUILL_LOG_DEBUG(log, "New State {}: ", nState);
153 newStateStep = step;
154 transitionStep = newStateStep;
155 firstTransitFlag = 1;
156 }
157 }
158
159 if (transitionFlag) {
160 QUILL_LOG_TRACE_L1(log, "Refining transition time.");
161 const bool can_refine =
162 params.parallel_replica_options().refine_transition && nRecord >= 2;
163 if (can_refine) {
165 refineStep = refine(mdBuffer, reactant.get());
167 newStateStep - StateCheckInterval + refineStep * RecordInterval;
168 transitionTime_current = timeBuffer[static_cast<size_t>(refineStep)];
169 transitionPot = biasBuffer[static_cast<size_t>(refineStep)];
170 const long prev = refineStep > 0 ? refineStep - 1 : 0;
171 *current = *mdBuffer[static_cast<size_t>(prev)];
172 } else {
173 refineStep = 0;
174 transitionTime_current = time;
175 transitionPot = boostPotential;
176 }
177 transitionTime = transitionTime_current - transitionTime_pre;
178 transitionTime_pre = transitionTime_current;
179 correctedTime =
180 (Temp > 0.0 && kB > 0.0)
181 ? transitionTime * std::exp((-1) * transitionPot / kB / Temp)
183 sumCorrectedTime += correctedTime;
184 if (nState == 1) {
185 firstTransitionTime = transitionTime;
186 }
187 velocity = current->getVelocities();
188 velocity = velocity * (-1);
189 current->setVelocities(velocity);
190
191 if (correctedTime < minCorrectedTime) {
192 minCorrectedTime = correctedTime;
193 if (can_refine) {
194 *saddle = *mdBuffer[static_cast<size_t>(refineStep)];
195 } else {
196 *saddle = *current;
197 }
199 }
200 QUILL_LOG_DEBUG(log,
201 "tranisitonTime= {:.3e} s, biasPot= {:.3f} eV, "
202 "correctedTime= {:.3e} s, "
203 "sumCorrectedTime= {:.3e} s, minCorTime= {:.3e} s",
204 transitionTime * 1e-15 * params.constants().timeUnit,
206 correctedTime * 1e-15 * params.constants().timeUnit,
207 sumCorrectedTime * 1e-15 * params.constants().timeUnit,
208 minCorrectedTime * 1.0e-15 * params.constants().timeUnit);
209
210 transitionFlag = false;
211 }
212
213 if (firstTransitFlag && sumCorrectedTime > firstTransitionTime) {
214 stopFlag = true;
215 newStateFlag = true;
216 }
217
218 if ((step % tenthSteps == 0) || (step == params.dynamics_options().steps)) {
219 double maxAtomDistance = current->perAtomNorm(*reactant);
220 QUILL_LOG_DEBUG(
221 log, "progress: {:.0f}%, max displacement: {:.3f}, step {} / {}",
222 static_cast<double>(100.0 * step / params.dynamics_options().steps),
223 maxAtomDistance, step, params.dynamics_options().steps);
224 }
225
226 // Honor dynamics step budget (parity with TADJob); without this the
227 // loop only exits on a confidence-gated transition and can run forever.
228 if (step >= params.dynamics_options().steps) {
229 stopFlag = true;
230 }
231 }
232
233 avgT = sumT / step;
234 varT = sumT2 / step - avgT * avgT;
235
236 if (nBoost > 0) {
237 QUILL_LOG_DEBUG(log,
238 "Temperature : Average = {:.6f} ; Stddev = {:.6f} ; "
239 "Factor = {:.6f}; Boost = {:.6f}",
240 avgT, std::sqrt(varT), varT / avgT / avgT * nFreeCoord / 2,
241 sumboost / nBoost);
242 } else {
243 QUILL_LOG_DEBUG(
244 log,
245 "Temperature : Average = {:.6f} ; Stddev = {:.6f} ; Factor = {:.6f}",
246 avgT, std::sqrt(varT), varT / avgT / avgT * nFreeCoord / 2);
247 }
248 if (std::isfinite(avgT) == 0) {
249 QUILL_LOG_DEBUG(log, "Infinite average temperature, something went wrong!");
250 newStateFlag = false;
251 }
252
253 // finalState is only filled on transition; keep product valid otherwise.
254 current->setBiasPotential(nullptr);
255
256 if (newStateFlag && finalState) {
258 } else if (current) {
259 *product = *current;
260 }
261
262 if (newStateFlag) {
263 return 1;
264 } else {
265 return 0;
266 }
267}
268
269} // namespace eonc
Eigen::Matrix< double, Eigen::Dynamic, 3, eOnStorageOrder > AtomMatrix
Definition Eigen.h:37
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.
void setThermalVelocity()
Definition Dynamics.cpp:247
void oneStep(int stepNumber=-1)
Definition Dynamics.cpp:57
RAII wrapper for tracking force calls over a scope.
static const char BOND_BOOST[]
Definition BondBoost.h:75
Parameters params
Definition Job.h:58
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 > saddle
std::shared_ptr< Matter > product
std::shared_ptr< Matter > finalState
std::shared_ptr< Matter > reactant
bool checkState(Matter *current, Matter *reactant)
Minimize a copy of current and compare to reactant.
std::shared_ptr< Matter > current
void dephase()
Dephase the trajectory to ensure thermal independence.
std::shared_ptr< Matter > finalStateTmp
void reportResults() override
Post-dynamics logging (override for job-specific messages).
std::vector< double > timeBuffer
std::vector< double > biasBuffer
int dynamics() override
The accelerated dynamics loop. Returns status (1 = transition, 0 = none).
RAII resource manager for the ARTn C library with global synchronization.