Loading...
Searching...
No Matches
TADJob.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/TADJob.h"
13#include "eon/Dynamics.h"
14#include "eon/ForceCallTimer.h"
15
16#include <cmath>
17
18namespace eonc {
19
21 crossing = std::make_shared<Matter>(pot, params);
22
23 QUILL_LOG_DEBUG(log, "Temperature Accelerated Dynamics, running");
24 QUILL_LOG_DEBUG(log,
25 "High temperature MD simulation running at {:.2f} K to "
26 "simulate dynamics at {:.2f} K",
27 params.main_options().temperature,
28 params.tad_options().low_temperature);
29}
30
32 if (newStateFlag) {
33 QUILL_LOG_DEBUG(log, "Transition time: {:.2e} s",
34 minCorrectedTime * 1.0e-15 * params.constants().timeUnit);
35 } else {
36 QUILL_LOG_DEBUG(log,
37 "No new state was found in {} dynamics steps ({:.3e} s)",
38 params.dynamics_options().steps,
39 time * 1.0e-15 * params.constants().timeUnit);
40 }
41}
42
44 bool transitionFlag = false, recordFlag = true, stopFlag = false,
45 firstTransitFlag = false;
46 long nFreeCoord = reactant->numberOfFreeAtoms() * 3;
47 long mdBufferLength;
48 long step = 0, refineStep, newStateStep = 0;
49 long nCheck = 0, nRecord = 0, nState = 0;
50 long StateCheckInterval, RecordInterval;
51 double kinE, kinT, avgT, varT;
52 double kB = params.constants().kB;
53 double correctedTime = 0.0;
54 double stopTime = 0.0, sumSimulatedTime = 0.0;
55 double Temp = 0.0, sumT = 0.0, sumT2 = 0.0;
56 double correctionFactor = 1.0;
57 double transitionTime_current = 0.0, transitionTime_previous = 0.0;
58 double delta, minmu, factor, highT, lowT;
59
60 AtomMatrix velocity;
61
62 minCorrectedTime = 1.0e200;
63 lowT = params.tad_options().low_temperature;
64 highT = params.main_options().temperature;
65 delta = params.tad_options().confidence;
66 minmu = params.tad_options().min_prefactor;
67 factor = std::log(1.0 / delta) / minmu;
68 const auto clock = prdClock();
69 StateCheckInterval = clock.state_check;
70 RecordInterval = clock.record;
71 Temp = params.main_options().temperature;
73
74 mdBufferLength = clock.buffer;
75 std::vector<std::shared_ptr<Matter>> mdBuffer(mdBufferLength);
76 for (long i = 0; i < mdBufferLength; i++) {
77 mdBuffer[i] = std::make_shared<Matter>(pot, params);
78 }
79 timeBuffer.resize(mdBufferLength);
80
81 Dynamics TAD(current.get(), params);
82 TAD.setThermalVelocity();
83
84 {
86 dephase();
87 }
88
89 QUILL_LOG_DEBUG(
90 log,
91 "Starting MD run\nTemperature: {:.2f} Kelvin"
92 "Total Simulation Time: {:.2f} fs\nTime Step: {:.2f} fs\nTotal Steps: "
93 "{}\n",
94 Temp,
95 params.dynamics_options().steps * params.dynamics_options().time_step *
96 params.constants().timeUnit,
97 params.dynamics_options().time_step * params.constants().timeUnit,
98 params.dynamics_options().steps);
99 QUILL_LOG_DEBUG(log, "MD buffer length: {}", mdBufferLength);
100
101 long tenthSteps = params.dynamics_options().steps / 10;
102 if (tenthSteps == 0) {
103 tenthSteps = params.dynamics_options().steps;
104 }
105
106 while (!stopFlag) {
107 kinE = current->getKineticEnergy();
108 kinT = (2.0 * kinE / nFreeCoord / kB);
109 sumT += kinT;
110 sumT2 += kinT * kinT;
111 QUILL_LOG_TRACE_L1(log, "steps = {:10d} temp = {:10.5f} ", step, kinT);
112
113 TAD.oneStep();
114 mdFCalls++;
115
116 time += params.dynamics_options().time_step;
117 nCheck++;
118 step++;
119 QUILL_LOG_TRACE_L1(log, "step = {:4d}, time= {:10.4f}", step, time);
120
121 if (params.parallel_replica_options().refine_transition && recordFlag &&
122 !newStateFlag) {
123 if (nCheck % RecordInterval == 0) {
124 *mdBuffer[nRecord] = *current;
125 timeBuffer[nRecord] = time;
126 nRecord++;
127 }
128 }
129
130 if ((nCheck == StateCheckInterval) && !newStateFlag) {
131 nCheck = 0;
132 nRecord = 0;
133 {
135 transitionFlag = checkState(current.get(), reactant.get());
136 }
137 if (transitionFlag) {
138 nState++;
139 QUILL_LOG_DEBUG(log, "New State {}: ", nState);
142 newStateStep = step;
143 transitionStep = newStateStep;
144 firstTransitFlag = 1;
145 }
146 }
147
148 if (transitionFlag) {
149 QUILL_LOG_TRACE_L1(log, "Refining transition time.");
150 const bool can_refine =
151 params.parallel_replica_options().refine_transition && nRecord >= 2;
152 if (can_refine) {
154 refineStep = refine(mdBuffer, reactant.get());
155 } else {
156 refineStep = 0;
157 }
158
159 if (can_refine) {
161 newStateStep - StateCheckInterval + refineStep * RecordInterval;
162 transitionTime_current = timeBuffer[static_cast<size_t>(refineStep)];
163 *crossing = *mdBuffer[static_cast<size_t>(refineStep)];
164 const long prev = refineStep > 0 ? refineStep - 1 : 0;
165 *current = *mdBuffer[static_cast<size_t>(prev)];
166 } else {
167 *crossing = *current;
168 transitionTime_current = time;
169 }
170 transitionTime = transitionTime_current - transitionTime_previous;
171 transitionTime_previous = transitionTime_current;
172 barrier = crossing->getPotentialEnergy() - reactant->getPotentialEnergy();
173 QUILL_LOG_DEBUG(log, "barrier= {:.3f}", barrier);
174 correctionFactor = std::exp(barrier / kB * (1.0 / lowT - 1.0 / highT));
175 correctedTime = transitionTime * correctionFactor;
176 sumSimulatedTime += transitionTime;
177 velocity = current->getVelocities();
178 velocity = velocity * (-1);
179 current->setVelocities(velocity);
180
181 if (correctedTime < minCorrectedTime) {
182 minCorrectedTime = correctedTime;
183 *saddle = *crossing;
185 }
186 stopTime = factor * std::pow(minCorrectedTime / factor, lowT / highT);
187 QUILL_LOG_DEBUG(
188 log,
189 "tranisitonTime= {:.3e} s, Barrier= {:.3f} eV, correctedTime= {:.3e} "
190 "s, "
191 "SimulatedTime= {:.3e} s, minCorTime= {:.3e} s, stopTime= {:.3e} s",
192 transitionTime * 1e-15 * params.constants().timeUnit, barrier,
193 correctedTime * 1e-15 * params.constants().timeUnit,
194 sumSimulatedTime * 1e-15 * params.constants().timeUnit,
195 minCorrectedTime * 1.0e-15 * params.constants().timeUnit,
196 stopTime * 1.0e-15 * params.constants().timeUnit);
197
198 transitionFlag = false;
199 }
200
201 if (firstTransitFlag && sumSimulatedTime >= stopTime) {
202 stopFlag = true;
203 newStateFlag = true;
204 }
205
206 if ((step % tenthSteps == 0) || (step == params.dynamics_options().steps)) {
207 double maxAtomDistance = current->perAtomNorm(*reactant);
208 QUILL_LOG_DEBUG(
209 log, "progress: {:.0f}%, max displacement: {:.3f}, step {}/{}",
210 static_cast<double>(100.0 * step) / params.dynamics_options().steps,
211 maxAtomDistance, step, params.dynamics_options().steps);
212 }
213
214 if (step == params.dynamics_options().steps) {
215 stopFlag = true;
216 if (firstTransitFlag) {
217 QUILL_LOG_DEBUG(log, "Detected one transition");
218 } else {
219 QUILL_LOG_DEBUG(log, "Failed to detect any transition");
220 }
221 }
222 }
223
224 avgT = sumT / step;
225 varT = sumT2 / step - avgT * avgT;
226
227 QUILL_LOG_DEBUG(log,
228 "Temperature : Average = {} ; Stddev = {} ; Factor = {}; "
229 "Average_Boost = {}",
230 avgT, std::sqrt(varT), varT / avgT / avgT * nFreeCoord / 2,
231 minCorrectedTime / step /
232 params.dynamics_options().time_step);
233 if (std::isfinite(avgT) == 0) {
234 QUILL_LOG_DEBUG(log, "Infinite average temperature, something went wrong!");
235 newStateFlag = false;
236 }
237
238 if (newStateFlag && finalState && finalState->numberOfAtoms() > 0) {
240 } else if (current) {
241 *product = *current;
242 }
243
244 if (newStateFlag) {
245 return 1;
246 } else {
247 return 0;
248 }
249}
250
251} // namespace eonc
Eigen::Matrix< double, Eigen::Dynamic, 3, eOnStorageOrder > AtomMatrix
Definition Eigen.h:37
RAII wrapper for tracking force calls over a scope.
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
std::shared_ptr< Matter > crossing
Definition TADJob.h:27
double barrier
Definition TADJob.h:28
void reportResults() override
Post-dynamics logging (override for job-specific messages).
Definition TADJob.cpp:31
void initExtra() override
Create any extra matter objects needed by the subclass.
Definition TADJob.cpp:20
int dynamics() override
The accelerated dynamics loop. Returns status (1 = transition, 0 = none).
Definition TADJob.cpp:43
std::vector< double > timeBuffer
Definition TADJob.h:29
RAII resource manager for the ARTn C library with global synchronization.