Loading...
Searching...
No Matches
ReplicaDynamicsJob.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*/
13#include "eon/BaseStructures.h"
14#include "eon/Dynamics.h"
15#include "eon/ForceCallTimer.h"
16#include "eon/HelperFunctions.h"
17#include <stdexcept>
18
19#include <format>
20#include <fstream>
21
22std::vector<std::string> ReplicaDynamicsJob::run() {
23 auto seed = std::make_shared<Matter>(pot, params);
24 std::string reactantFilename =
25 eonc::helpers::getRelevantFile(params.main_options.conFilename);
26 if (!eonc::io::io_ok(seed->con2matter(reactantFilename))) {
27 QUILL_LOG_CRITICAL(log, "Failed to load {}", reactantFilename);
28 throw std::runtime_error("failed to load " + reactantFilename);
29 }
30 (void)runFromMatter(std::move(seed));
31 return returnFiles;
32}
33
34std::shared_ptr<Matter>
35ReplicaDynamicsJob::runFromMatter(std::shared_ptr<Matter> initial) {
36 if (!initial) {
37 throw std::runtime_error("runFromMatter: initial Matter is null");
38 }
39 current = initial;
40 current->setPotential(pot);
41 reactant = std::make_shared<Matter>(pot, params);
42 saddle = std::make_shared<Matter>(pot, params);
43 product = std::make_shared<Matter>(pot, params);
44 finalState = std::make_shared<Matter>(pot, params);
45 finalStateTmp = std::make_shared<Matter>(pot, params);
46
48 time = 0.0;
49
50 QUILL_LOG_DEBUG(log, "Minimizing initial reactant");
51 {
53 *reactant = *current;
54 reactant->relax();
55 }
56
57 initExtra();
58
59 int status = dynamics();
60
61 saveData(status);
63
64 return current;
65}
66
68 Matter tmp(pot, params);
69 tmp = *curr;
70 tmp.relax(true);
71 return !tmp.compare(*react);
72}
73
75 const std::vector<std::shared_ptr<Matter>> &buff, Matter *react) {
76 QUILL_LOG_TRACE_L1(log, "Refining transition time.");
77
78 long lo = 0;
79 long hi = static_cast<long>(buff.size()) - 1;
80
81 while ((hi - lo) > 1) {
82 long mid = lo + (hi - lo) / 2;
83 if (!checkState(buff[mid].get(), react)) {
84 lo = mid;
85 } else {
86 hi = mid;
87 }
88 }
89
90 return (lo + hi) / 2 + 1;
91}
92
94 long DephaseSteps =
95 static_cast<long>(params.parallel_replica_options.dephase_time /
96 params.dynamics_options.time_step);
97 Dynamics dephaseDynamics(current.get(), params);
98 QUILL_LOG_DEBUG(log, "Dephasing for {:.2f} fs",
99 params.parallel_replica_options.dephase_time *
100 params.constants.timeUnit);
101
102 long step = 0, loop = 0;
103
104 while (step < DephaseSteps) {
105 long dephaseBufferLength = DephaseSteps - step;
106 loop++;
107 std::vector<std::shared_ptr<Matter>> dephaseBuffer(dephaseBufferLength);
108
109 for (long i = 0; i < dephaseBufferLength; i++) {
110 dephaseBuffer[i] = std::make_shared<Matter>(pot, params);
111 dephaseDynamics.oneStep();
112 *dephaseBuffer[i] = *current;
113 }
114
115 bool transitionFlag = checkState(current.get(), reactant.get());
116
117 if (transitionFlag) {
118 long dephaseRefineStep = refine(dephaseBuffer, reactant.get());
119 QUILL_LOG_DEBUG(log, "loop = {}; dephase refine step = {}", loop,
120 dephaseRefineStep);
121 long ts = dephaseRefineStep - 1;
122 ts = (ts > 0) ? ts : 0;
123 QUILL_LOG_DEBUG(
124 log,
125 "Dephasing warning: in a new state, inverse the momentum and restart "
126 "from step {}",
127 step + ts);
128 *current = *dephaseBuffer[ts];
129 AtomMatrix velocity = current->getVelocities();
130 velocity = velocity * (-1);
131 current->setVelocities(velocity);
132 step = step + ts;
133 } else {
134 step = step + dephaseBufferLength;
135 QUILL_LOG_TRACE_L1(log, "Successful dephasing for {} steps", step);
136 }
137
138 if ((params.parallel_replica_options.dephase_loop_stop) &&
139 (loop > params.parallel_replica_options.dephase_loop_max)) {
140 QUILL_LOG_DEBUG(
141 log,
142 "Reach dephase loop maximum, stop dephasing! Dephased for {} steps",
143 step);
144 break;
145 }
146 QUILL_LOG_DEBUG(log, "Successfully Dephased for {:.2f} fs",
147 step * params.dynamics_options.time_step *
148 params.constants.timeUnit);
149 }
150}
151
153 std::string resultsFilename("results.dat");
154 returnFiles.push_back(resultsFilename);
155 size_t totalFCalls = minimizeFCalls + mdFCalls + dephaseFCalls + refineFCalls;
156
157 {
158 std::ofstream out(resultsFilename, std::ios::binary);
159 if (out) {
160 out << std::format(
161 "{} potential_type\n",
162 magic_enum::enum_name<PotType>(params.potential_options.potential));
163 out << std::format("{} random_seed\n", params.main_options.randomSeed);
164 out << std::format("{:f} potential_energy_reactant\n",
165 reactant->getPotentialEnergy());
166 out << std::format("{} total_force_calls\n", totalFCalls);
167 out << std::format("{} force_calls_dephase\n", dephaseFCalls);
168 out << std::format("{} force_calls_dynamics\n", mdFCalls);
169 out << std::format("{} force_calls_minimize\n", minimizeFCalls);
170 out << std::format("{} force_calls_refine\n", refineFCalls);
171 out << std::format("{} transition_found\n", (newStateFlag) ? 1 : 0);
172
173 if (newStateFlag) {
174 out << std::format("{:e} transition_time_s\n",
175 minCorrectedTime * 1.0e-15 *
176 params.constants.timeUnit);
177 out << std::format("{:f} potential_energy_product\n",
178 product->getPotentialEnergy());
179 out << std::format("{:f} moved_distance\n",
180 product->distanceTo(*reactant));
181 }
182
183 out << std::format("{:e} simulation_time_s\n",
184 time * 1.0e-15 * params.constants.timeUnit);
185 out << std::format("{:f} speedup\n",
186 time / params.dynamics_options.steps /
187 params.dynamics_options.time_step);
188 }
189 }
190
191 std::string reactantFilename("reactant.con");
192 returnFiles.push_back(reactantFilename);
193 if (!eonc::io::io_ok(reactant->matter2con(reactantFilename))) {
194 QUILL_LOG_ERROR(log, "Failed to write {}", reactantFilename);
195 }
196
197 if (newStateFlag) {
198 std::string productFilename("product.con");
199 returnFiles.push_back(productFilename);
200 if (!eonc::io::io_ok(product->matter2con(productFilename))) {
201 QUILL_LOG_ERROR(log, "Failed to write {}", productFilename);
202 }
203
204 if (params.parallel_replica_options.refine_transition) {
205 std::string saddleFilename("saddle.con");
206 returnFiles.push_back(saddleFilename);
207 if (!eonc::io::io_ok(saddle->matter2con(saddleFilename))) {
208 QUILL_LOG_ERROR(log, "Failed to write {}", saddleFilename);
209 }
210 }
211 }
212}
Eigen::Matrix< double, Eigen::Dynamic, 3, eOnStorageOrder > AtomMatrix
Definition Eigen.h:37
std::vector< std::string > run() override
Virtual run; used solely for dynamic dispatch.
void oneStep(int stepNumber=-1)
Definition Dynamics.cpp:41
RAII wrapper for tracking force calls over a scope.
std::shared_ptr< Potential > pot
Definition Job.h:55
Parameters params
Definition Job.h:54
bool relax(bool quiet=false, bool writeMovie=false, bool checkpoint=false, std::string prefixMovie=std::string(), std::string prefixCheckpoint=std::string(), bool retainMovieFrames=false)
Definition Matter.cpp:257
bool compare(const Matter &matter, bool indistinguishable=false)
Definition Matter.cpp:129
void dephase()
Dephase the trajectory to ensure thermal independence.
std::vector< std::string > returnFiles
std::shared_ptr< Matter > saddle
std::shared_ptr< Matter > product
std::shared_ptr< Matter > runFromMatter(std::shared_ptr< Matter > initial)
Matter-first entry: seed geometry, skip con2matter load.
long refine(const std::vector< std::shared_ptr< Matter > > &buff, Matter *reactant)
Binary search for the transition frame in a snapshot buffer.
virtual int dynamics()=0
The accelerated dynamics loop. Returns status (1 = transition, 0 = none).
std::shared_ptr< Matter > finalState
virtual void initExtra()
Create any extra matter objects needed by the subclass.
virtual void reportResults()
Post-dynamics logging (override for job-specific messages).
std::shared_ptr< Matter > reactant
void saveData(int status)
Write results.dat and structure con files.
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
std::string getRelevantFile(std::string filename)
constexpr bool io_ok(IoStatus s) noexcept
Definition ConFileIO.h:38