42 throw std::runtime_error(
"ParallelReplicaJob::runFromMatter: null Matter");
47 QUILL_LOG_DEBUG(
log,
"[ParallelReplica] Minimizing initial position");
50 QUILL_LOG_ERROR(
log,
"Failed to write reactant.con");
53 auto trajectory = std::make_shared<Matter>(
pot,
params);
58 if (
params.hyperdynamics_options.bias_potential ==
61 trajectory->setBiasPotential(&bondBoost);
66 int stateCheckInterval =
static_cast<int>(
67 std::floor(
params.parallel_replica_options.state_check_interval /
68 params.dynamics_options.time_step +
70 int recordInterval =
static_cast<int>(
71 std::floor(
params.parallel_replica_options.record_interval /
72 params.dynamics_options.time_step +
74 if (stateCheckInterval < 1)
75 stateCheckInterval = 1;
76 if (recordInterval < 1)
79 std::vector<std::shared_ptr<Matter>> mdSnapshots;
80 std::vector<double> mdTimes;
81 double transitionTime = 0;
83 size_t refineForceCalls = 0;
85 double simulationTime = 0.0;
88 log,
"[ParallelReplica] {:>8} {:>12} {:>10} {:>12} {:>12} {:>10}",
89 "Step",
"Time (s)",
"KE",
"PE",
"TE",
"KinT");
93 "[ParallelReplica] {:>8} {:>12} {:>10} {:>10} {:>12} {:>12} {:>10}",
94 "Step",
"Time (s)",
"Boost",
"KE",
"PE",
"TE",
"KinT");
97 for (
int step = 1; step <=
params.dynamics_options.steps; step++) {
98 if (
params.hyperdynamics_options.bias_potential ==
107 if (
params.hyperdynamics_options.bias_potential ==
109 double boostPotential = bondBoost.
boost();
110 double kB =
params.constants.kB;
111 boost = std::exp(boostPotential / kB /
params.main_options.temperature);
112 simulationTime +=
params.dynamics_options.time_step * boost;
114 simulationTime +=
params.dynamics_options.time_step;
117 double kinE = trajectory->getKineticEnergy();
118 double potE = trajectory->getPotentialEnergy();
119 double kinT = (2.0 * kinE / (trajectory->numberOfFreeAtoms() * 3) /
122 if (step %
params.debug_options.write_movies_interval == 0) {
125 "[ParallelReplica] {:>8} {:>12.4e} {:>10.4f} "
126 "{:>12.4f} {:>12.4f} {:>10.2f}",
128 simulationTime *
params.constants.timeUnit * 1e-15,
129 kinE, potE, kinE + potE, kinT);
131 double boostPotential = bondBoost.
boost();
134 "[ParallelReplica] {:>8} {:>12.4e} {:>10.3e} "
135 "{:>10.4f} {:>12.4f} {:>12.4f} {:>10.2f}",
136 step, simulationTime *
params.constants.timeUnit * 1e-15, boost,
137 kinE, potE + boostPotential, kinE + potE + boostPotential, kinT);
142 if (step % recordInterval == 0 &&
143 params.parallel_replica_options.refine_transition) {
144 auto snap = std::make_shared<Matter>(
pot,
params);
146 mdSnapshots.push_back(std::move(snap));
147 mdTimes.push_back(simulationTime);
151 if (step % stateCheckInterval == 0 ||
152 step ==
params.dynamics_options.steps) {
153 QUILL_LOG_DEBUG(
log,
"[ParallelReplica] Checking for transition");
156 minimized = *trajectory;
160 QUILL_LOG_DEBUG(
log,
"[ParallelReplica] Transition occurred");
162 if (
params.parallel_replica_options.refine_transition &&
163 !mdSnapshots.empty() && !mdTimes.empty()) {
164 QUILL_LOG_DEBUG(
log,
"[ParallelReplica] Refining transition time");
170 if (snapshotIndex < 0)
172 if (snapshotIndex >=
static_cast<int>(mdSnapshots.size()))
173 snapshotIndex =
static_cast<int>(mdSnapshots.size()) - 1;
175 transitionTime = mdTimes[
static_cast<size_t>(snapshotIndex)];
176 transitionStructure =
177 *mdSnapshots[
static_cast<size_t>(snapshotIndex)];
179 transitionStructure = *trajectory;
180 transitionTime = simulationTime;
182 QUILL_LOG_DEBUG(
log,
"[ParallelReplica] Transition time: {:.3e} s",
183 transitionTime *
params.constants.timeUnit * 1e-15);
185 }
else if (step + 1 ==
params.dynamics_options.steps &&
186 transitionTime == 0) {
188 if (
params.parallel_replica_options.refine_transition &&
189 !mdSnapshots.empty()) {
192 "[ParallelReplica] Simulation ended without seeing a transition");
194 log,
"[ParallelReplica] Refining anyways to prevent bias...");
200 transitionStructure = *trajectory;
209 int decorrelationSteps =
210 static_cast<int>(std::floor(
params.parallel_replica_options.corr_time /
211 params.dynamics_options.time_step +
213 QUILL_LOG_DEBUG(
log,
"[ParallelReplica] Decorrelating: {} steps",
215 for (
int step = 1; step <= decorrelationSteps; step++) {
218 QUILL_LOG_DEBUG(
log,
"[ParallelReplica] Decorrelation complete");
222 product = *trajectory;
225 QUILL_LOG_ERROR(
log,
"Failed to write product.con");
229 std::string resultsFilename(
"results.dat");
232 std::ofstream out(resultsFilename, std::ios::binary);
235 "{} potential_type\n",
236 magic_enum::enum_name<PotType>(
params.potential_options.potential));
237 out << std::format(
"{} random_seed\n",
params.main_options.randomSeed);
238 out << std::format(
"{:f} potential_energy_reactant\n",
240 out << std::format(
"{} force_calls_refine\n", refineForceCalls);
241 out << std::format(
"{} total_force_calls\n",
244 if (transitionTime == 0) {
245 out <<
"0 transition_found\n";
246 out << std::format(
"{:e} simulation_time_s\n",
247 simulationTime *
params.constants.timeUnit *
250 out <<
"1 transition_found\n";
251 out << std::format(
"{:e} transition_time_s\n",
252 transitionTime *
params.constants.timeUnit *
254 out << std::format(
"{:e} correlation_time_s\n",
255 params.parallel_replica_options.corr_time *
256 params.constants.timeUnit * 1.0e-15);
257 out << std::format(
"{:f} potential_energy_product\n",
260 out << std::format(
"{:f} speedup\n",
261 simulationTime / (
params.dynamics_options.steps *
262 params.dynamics_options.time_step));
270 trajectory->setBiasPotential(
nullptr);