Loading...
Searching...
No Matches
BondBoost.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
13#include "eon/BondBoost.h"
14#include "eon/EonLogger.h"
15#include "eon/HelperFunctions.h"
16
17#include <algorithm>
18#include <cmath>
19#include <string>
20#include <vector>
21
22const char Hyperdynamics::NONE[] = "none";
23const char Hyperdynamics::BOND_BOOST[] = "bond_boost";
24
26 : matter{matt},
27 parameters{params} {
28 nAtoms = matter->numberOfAtoms();
29}
30
31BondBoost::~BondBoost() = default;
32
34 nBBs = 0;
35 nReg = 1;
36
37 const std::string &balString =
38 parameters.hyperdynamics_options.boost_atom_list;
39 auto atoms = eonc::helpers::split_string_int(balString, ",");
40
41 if (balString == "all" || atoms.empty()) {
42 QUILL_LOG_DEBUG(log, "boost all atoms that are set free\n");
43 nBAs = matter->numberOfFreeAtoms();
44 nRAs = nAtoms - nBAs;
45 BAList.resize(nBAs);
46 RAList.resize(nRAs);
47 long k = 0;
48 for (long i = 0; i < nAtoms; i++) {
49 if (!matter->getFixed(i)) {
50 BAList[k++] = i;
51 }
52 }
53 } else {
54 QUILL_LOG_DEBUG(log, "boost the following selected atoms:");
55 for (size_t i = 0; i < atoms.size(); i++) {
56 QUILL_LOG_DEBUG(log, "{} ", atoms[i]);
57 }
58 QUILL_LOG_DEBUG(log, "\n");
59 nBAs = static_cast<long>(atoms.size());
60 nRAs = nAtoms - nBAs;
61 BAList.resize(nBAs);
62 RAList.resize(nRAs);
63 for (long i = 0; i < nBAs; i++) {
64 BAList[i] = atoms[i];
65 }
66 }
67
68 // Build rest-atoms list (atoms not in BAList)
69 long count = 0;
70 for (long i = 0; i < nAtoms; i++) {
71 bool isBoosted = std::any_of(BAList.begin(), BAList.end(),
72 [i](long ba) { return ba == i; });
73 if (!isBoosted) {
74 RAList[count++] = i;
75 }
76 }
77 if (count != nRAs) {
78 QUILL_LOG_DEBUG(log, "Error: nRestAtoms does not equal counted number!\n");
79 }
80
81 nTABs = nBAs * (nBAs - 1) / 2 + nBAs * nRAs;
82 TABAList.resize(2 * nTABs);
83 TABLList.setZero(nTABs, 1);
84 QUILL_LOG_DEBUG(log, "BondBoost Used !\n");
85}
86
87long BondBoost::rmdSteps() const {
88 return static_cast<long>(parameters.hyperdynamics_options.rmd_time /
89 parameters.dynamics_options.time_step);
90}
91
93 const long RMDS = rmdSteps();
94 if (nReg <= RMDS) {
95 // Equilibration: sample bond lengths once per MD step.
96 Matrix<double, Eigen::Dynamic, 1> TABL_tmp = Rmdsteps();
97 TABLList = TABLList + (1.0 / RMDS) * TABL_tmp;
98 nReg++;
99 if (nReg == RMDS + 1) {
100 nBBs = BondSelect();
101 }
102 return;
103 }
104 if (nReg == RMDS + 1) {
105 nBBs = BondSelect();
106 }
107 nReg++;
108}
109
111 const long RMDS = rmdSteps();
112 if (nReg <= RMDS) {
113 return 0.0;
114 }
115 // RMDS == 0 and a caller that never advance()s still has to select bonds
116 // on the first evaluation; SafeHyper / ParallelReplica call advance()
117 // first and reach BondSelect there.
118 if (nBBs == 0) {
119 nBBs = BondSelect();
120 }
121 Epsr_Q.resize(nBBs);
122 CBBLList.setZero(nBBs, 1);
123 const double biasPot = Booststeps();
124 Epsr_Q.clear();
125 return biasPot;
126}
127
131 const double QRR = parameters.hyperdynamics_options.qrr;
132 const double PRR = parameters.hyperdynamics_options.prr;
133 const double DVMAX = parameters.hyperdynamics_options.dvmax;
134 const double nBBsD = static_cast<double>(nBBs);
135
136 AtomMatrix addForces(nBBs, 3);
137 AtomMatrix TADF(nAtoms, 3);
138 addForces.setZero();
139 TADF.setZero();
140
141 // Measure current bond lengths
142 for (long i = 0; i < nBBs; i++) {
143 CBBLList(i, 0) = matter->distance(BBAList[2 * i], BBAList[2 * i + 1]);
144 }
145
146 // Compute strain parameters and find maximum
147 double epsrMax = 0.0;
148 for (long i = 0; i < nBBs; i++) {
149 Epsr_Q[i] = (CBBLList(i, 0) - EBBLList(i, 0)) / EBBLList(i, 0) / QRR;
150 if (std::abs(Epsr_Q[i]) >= epsrMax) {
151 epsrMax = std::abs(Epsr_Q[i]);
152 }
153 }
154
155 // Envelope function A(eps_max)
156 double A_eps = (1.0 - epsrMax * epsrMax) * (1.0 - epsrMax * epsrMax) /
157 (1.0 - PRR * PRR * epsrMax * epsrMax);
158
159 // Sum of individual bias potentials
160 double sumV = 0.0;
161 if (epsrMax < 1.0) {
162 for (long i = 0; i < nBBs; i++) {
163 sumV += DVMAX * (1.0 - Epsr_Q[i] * Epsr_Q[i]) / nBBsD;
164 }
165 } else {
166 A_eps = 0.0;
167 }
168
169 double boostFact = A_eps * sumV;
170
171 // Compute bias forces per bond, accumulate on atoms
172 for (long i = 0; i < nBBs; i++) {
173 double dforce = 0.0;
174 double fact1 =
175 2.0 * A_eps * DVMAX * Epsr_Q[i] / QRR / EBBLList(i, 0) / nBBsD;
176
177 if (std::abs(Epsr_Q[i]) < epsrMax) {
178 dforce = fact1;
179 } else {
180 // Bond at maximum strain: additional envelope derivative
181 double fTmp1 = 1.0 - PRR * PRR * Epsr_Q[i] * Epsr_Q[i];
182 double fTmp2 = 1.0 - Epsr_Q[i] * Epsr_Q[i];
183 double fact2 = 2.0 * fTmp2 * Epsr_Q[i] *
184 (2.0 * fTmp1 - PRR * PRR * fTmp2) / QRR / EBBLList(i, 0) /
185 fTmp1 / fTmp1;
186 dforce = fact1 + sumV * fact2;
187 }
188
189 long a1 = BBAList[2 * i];
190 long a2 = BBAList[2 * i + 1];
191 double R = CBBLList(i, 0);
192
193 for (int j = 0; j < 3; j++) {
194 double rij = matter->pdistance(a1, a2, j);
195 double fij = rij / R * dforce;
196 addForces(i, j) = fij;
197 TADF(a1, j) += fij;
198 TADF(a2, j) -= fij;
199 }
200 }
201
202 // Apply free-atom mask and set bias forces
203 AtomMatrix biasForces = TADF.array() * matter->getFree().array();
204 matter->setBiasForces(biasForces);
205 return boostFact;
206}
207
209Matrix<double, Eigen::Dynamic, 1> BondBoost::Rmdsteps() {
210 Matrix<double, Eigen::Dynamic, 1> bondLengths(nTABs, 1);
211 long count = 0;
212
213 // Boost-atom pairs
214 for (long i = 0; i < nBAs; i++) {
215 for (long j = i + 1; j < nBAs; j++) {
216 bondLengths(count, 0) = matter->distance(BAList[i], BAList[j]);
217 TABAList[2 * count] = BAList[i];
218 TABAList[2 * count + 1] = BAList[j];
219 count++;
220 }
221 }
222
223 // Boost-atom to rest-atom pairs
224 for (long i = 0; i < nBAs; i++) {
225 for (long j = 0; j < nRAs; j++) {
226 bondLengths(count, 0) = matter->distance(BAList[i], RAList[j]);
227 TABAList[2 * count] = BAList[i];
228 TABAList[2 * count + 1] = RAList[j];
229 count++;
230 }
231 }
232
233 if (count != nTABs) {
234 QUILL_LOG_DEBUG(log, "Total involved bond count does not match expected\n");
235 }
236 return bondLengths;
237}
238
241 const double qCutoff = parameters.hyperdynamics_options.qcut;
242
243 // Count bonds within cutoff
244 long nSelected = 0;
245 for (long i = 0; i < nTABs; i++) {
246 if (TABLList(i, 0) <= qCutoff) {
247 nSelected++;
248 }
249 }
250
251 EBBLList.setZero(nSelected, 1);
252 BBAList.resize(2 * nSelected);
253 long count = 0;
254 for (long i = 0; i < nTABs; i++) {
255 if (TABLList(i, 0) <= qCutoff) {
256 EBBLList(count, 0) = TABLList(i, 0);
257 BBAList[2 * count] = TABAList[2 * i];
258 BBAList[2 * count + 1] = TABAList[2 * i + 1];
259 count++;
260 }
261 }
262 return nSelected;
263}
Eigen::Matrix< double, Eigen::Dynamic, 3, eOnStorageOrder > AtomMatrix
Definition Eigen.h:37
BondBoost(Matter *matt, const Parameters &params)
Constructor to be used when a structure is minimized.
Definition BondBoost.cpp:25
static const char NONE[]
Definition BondBoost.h:76
static const char BOND_BOOST[]
Definition BondBoost.h:77
const Parameters & parameters
Reference to a structure outside the scope of the class containing runtime parameters.
Definition BondBoost.h:53
long BondSelect()
Select bonds within cutoff distance for boosting.
Matter * matter
Pointer to atom object outside the scope of the class.
Definition BondBoost.h:51
long nAtoms
Number of free coordinates.
Definition BondBoost.h:50
Matrix< double, Eigen::Dynamic, 1 > EBBLList
Definition BondBoost.h:62
double Booststeps()
Compute bias potential and forces for bond-boost hyperdynamics.
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
eonc::log::Scoped log
Definition BondBoost.h:69
Matrix< double, Eigen::Dynamic, 1 > Rmdsteps()
Measure all tagged-atom bond lengths for the equilibration phase.
std::vector< long > BBAList
Definition BondBoost.h:58
Matrix< double, Eigen::Dynamic, 1 > TABLList
Definition BondBoost.h:61
std::vector< double > Epsr_Q
Definition BondBoost.h:59
std::vector< long > TABAList
Definition BondBoost.h:57
long rmdSteps() const
Definition BondBoost.cpp:87
std::vector< long > BAList
Definition BondBoost.h:55
Matrix< double, Eigen::Dynamic, 1 > CBBLList
Definition BondBoost.h:63
~BondBoost()
Destructor.
std::vector< long > RAList
Definition BondBoost.h:56
std::vector< int > split_string_int(std::string s, std::string delim)