eOn 3.2.0
Long-timescale dynamics: aKMC, NEB, parallel replica
☾
Toggle main menu visibility
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 <cctype>
19
#include <cmath>
20
#include <ranges>
21
#include <stdexcept>
22
#include <string>
23
#include <unordered_set>
24
#include <vector>
25
26
namespace
eonc
{
27
28
const
char
Hyperdynamics::NONE
[] =
"none"
;
29
const
char
Hyperdynamics::BOND_BOOST
[] =
"bond_boost"
;
30
31
BondBoost::BondBoost
(
Matter
*matt,
const
Parameters
¶ms)
32
:
matter
{matt},
33
parameters
{params} {
34
if
(!
matter
) {
35
throw
std::invalid_argument(
"BondBoost: null Matter"
);
36
}
37
nAtoms
=
matter
->numberOfAtoms();
38
}
39
40
BondBoost::~BondBoost
() =
default
;
41
42
void
BondBoost::initialize
() {
43
nBBs
= 0;
44
nReg
= 1;
45
46
const
std::string &balString =
47
parameters
.hyperdynamics_options().boost_atom_list;
48
std::string lowered = balString;
49
std::ranges::transform(lowered, lowered.begin(), [](
unsigned
char
c) {
50
return static_cast<char>(std::tolower(c));
51
});
52
53
BAList
.clear();
54
if
(lowered.empty() || lowered ==
"all"
) {
55
for
(
long
i = 0; i <
nAtoms
; ++i) {
56
if
(!
matter
->getFixed(i)) {
57
BAList
.push_back(i);
58
}
59
}
60
}
else
{
61
const
auto
atoms =
eonc::helpers::split_string_int
(balString,
","
);
62
if
(atoms.empty()) {
63
throw
std::invalid_argument(
64
"hyperdynamics.boost_atom_list must be 'all' or a comma list of "
65
"CON file-order indices"
);
66
}
67
std::unordered_set<long> seen;
68
for
(
int
raw : atoms) {
69
const
long
row =
matter
->mapFileRow(
static_cast<
long
>
(raw));
70
if
(row < 0 || row >=
nAtoms
) {
71
throw
std::out_of_range(
72
"hyperdynamics.boost_atom_list index out of range"
);
73
}
74
if
(
matter
->getFixed(row)) {
75
continue
;
76
}
77
if
(seen.insert(row).second) {
78
BAList
.push_back(row);
79
}
80
}
81
}
82
if
(
BAList
.empty()) {
83
throw
std::runtime_error(
"BondBoost: no boostable atoms"
);
84
}
85
86
nBAs
=
static_cast<
long
>
(
BAList
.size());
87
const
std::unordered_set<long> boosted(
BAList
.begin(),
BAList
.end());
88
RAList
.clear();
89
RAList
.reserve(
static_cast<
size_t
>
(
nAtoms
-
nBAs
));
90
for
(
long
i = 0; i <
nAtoms
; ++i) {
91
if
(boosted.find(i) == boosted.end()) {
92
RAList
.push_back(i);
93
}
94
}
95
nRAs
=
static_cast<
long
>
(
RAList
.size());
96
97
nTABs
=
nBAs
* (
nBAs
- 1) / 2 +
nBAs
*
nRAs
;
98
TABAList
.assign(
static_cast<
size_t
>
(2 * std::max(
nTABs
, 0L)), 0);
99
TABLList
.setZero(
nTABs
, 1);
100
QUILL_LOG_DEBUG(
log
,
"BondBoost: {} boost atoms, {} rest, {} tagged bonds"
,
101
nBAs
,
nRAs
,
nTABs
);
102
}
103
104
long
BondBoost::rmdSteps
()
const
{
105
const
double
dt =
parameters
.dynamics_options().time_step;
106
if
(!(dt > 0.0)) {
107
return
0;
108
}
109
return
static_cast<
long
>
(
parameters
.hyperdynamics_options().rmd_time / dt);
110
}
111
112
void
BondBoost::advance
() {
113
const
long
RMDS =
rmdSteps
();
114
// nReg starts at 1, so a zero sample count never enters the average below
115
// and never divides by RMDS. TABLList would stay the zeros from
116
// initialize(), and BondSelect would keep every tagged pair at length 0.
117
if
(RMDS <= 0) {
118
if
(
nBBs
== 0) {
119
TABLList
=
Rmdsteps
();
120
nBBs
=
BondSelect
();
121
}
122
nReg
++;
123
return
;
124
}
125
if
(
nReg
<= RMDS) {
126
// Equilibration: sample bond lengths once per MD step.
127
Matrix<double, Eigen::Dynamic, 1> TABL_tmp =
Rmdsteps
();
128
TABLList
=
TABLList
+ (1.0 / RMDS) * TABL_tmp;
129
nReg
++;
130
if
(
nReg
== RMDS + 1) {
131
nBBs
=
BondSelect
();
132
}
133
return
;
134
}
135
if
(
nReg
== RMDS + 1) {
136
nBBs
=
BondSelect
();
137
}
138
nReg
++;
139
}
140
141
double
BondBoost::boost
() {
142
const
long
RMDS =
rmdSteps
();
143
if
(RMDS > 0 &&
nReg
<= RMDS) {
144
return
0.0;
145
}
146
// Callers that never advance() still select on the first evaluation.
147
// With no equilibration samples that selection has to measure lengths
148
// first; SafeHyper and ParallelReplica advance() before they get here.
149
if
(
nBBs
== 0) {
150
if
(RMDS <= 0) {
151
TABLList
=
Rmdsteps
();
152
}
153
nBBs
=
BondSelect
();
154
}
155
Epsr_Q
.resize(
nBBs
);
156
CBBLList
.setZero(
nBBs
, 1);
157
const
double
biasPot =
Booststeps
();
158
Epsr_Q
.clear();
159
return
biasPot;
160
}
161
164
double
BondBoost::Booststeps
() {
165
const
double
QRR =
parameters
.hyperdynamics_options().qrr;
166
const
double
PRR =
parameters
.hyperdynamics_options().prr;
167
const
double
DVMAX =
parameters
.hyperdynamics_options().dvmax;
168
if
(
nBBs
<= 0 || !(QRR > 0.0)) {
169
return
0.0;
170
}
171
const
double
nBBsD =
static_cast<
double
>
(
nBBs
);
172
173
AtomMatrix
addForces(
nBBs
, 3);
174
AtomMatrix
TADF(
nAtoms
, 3);
175
addForces.setZero();
176
TADF.setZero();
177
178
// Measure current bond lengths
179
for
(
long
i = 0; i <
nBBs
; i++) {
180
CBBLList
(i, 0) =
matter
->distance(
BBAList
[2 * i],
BBAList
[2 * i + 1]);
181
}
182
183
// Compute strain parameters and find maximum
184
double
epsrMax = 0.0;
185
for
(
long
i = 0; i <
nBBs
; i++) {
186
const
double
eq =
EBBLList
(i, 0);
187
if
(!(eq > 0.0)) {
188
Epsr_Q
[i] = 0.0;
189
continue
;
190
}
191
Epsr_Q
[i] = (
CBBLList
(i, 0) - eq) / eq / QRR;
192
if
(std::abs(
Epsr_Q
[i]) >= epsrMax) {
193
epsrMax = std::abs(
Epsr_Q
[i]);
194
}
195
}
196
197
// Envelope function A(eps_max)
198
double
A_eps = (1.0 - epsrMax * epsrMax) * (1.0 - epsrMax * epsrMax) /
199
(1.0 - PRR * PRR * epsrMax * epsrMax);
200
201
// Sum of individual bias potentials
202
double
sumV = 0.0;
203
if
(epsrMax < 1.0) {
204
for
(
long
i = 0; i <
nBBs
; i++) {
205
sumV += DVMAX * (1.0 -
Epsr_Q
[i] *
Epsr_Q
[i]) / nBBsD;
206
}
207
}
else
{
208
A_eps = 0.0;
209
}
210
211
double
boostFact = A_eps * sumV;
212
213
// Compute bias forces per bond, accumulate on atoms
214
for
(
long
i = 0; i <
nBBs
; i++) {
215
double
dforce = 0.0;
216
double
fact1 =
217
2.0 * A_eps * DVMAX *
Epsr_Q
[i] / QRR /
EBBLList
(i, 0) / nBBsD;
218
219
if
(std::abs(
Epsr_Q
[i]) < epsrMax) {
220
dforce = fact1;
221
}
else
{
222
// Bond at maximum strain: additional envelope derivative
223
double
fTmp1 = 1.0 - PRR * PRR *
Epsr_Q
[i] *
Epsr_Q
[i];
224
double
fTmp2 = 1.0 -
Epsr_Q
[i] *
Epsr_Q
[i];
225
double
fact2 = 2.0 * fTmp2 *
Epsr_Q
[i] *
226
(2.0 * fTmp1 - PRR * PRR * fTmp2) / QRR /
EBBLList
(i, 0) /
227
fTmp1 / fTmp1;
228
dforce = fact1 + sumV * fact2;
229
}
230
231
long
a1 =
BBAList
[2 * i];
232
long
a2 =
BBAList
[2 * i + 1];
233
if
(!(
EBBLList
(i, 0) > 0.0)) {
234
continue
;
235
}
236
// distance() minimum-images the whole bond. pdistance minimum-images one
237
// Cartesian axis after zeroing the other two, which is not that vector
238
// when the cell is non-orthogonal.
239
AtomMatrix
delta(1, 3);
240
delta.row(0) =
241
matter
->getPositions().row(a1) -
matter
->getPositions().row(a2);
242
delta =
matter
->pbc(delta);
243
const
double
R = delta.norm();
244
if
(!(R > 0.0)) {
245
continue
;
246
}
247
248
for
(
int
j = 0; j < 3; j++) {
249
const
double
rij = delta(0, j);
250
const
double
fij = rij / R * dforce;
251
addForces(i, j) = fij;
252
TADF(a1, j) += fij;
253
TADF(a2, j) -= fij;
254
}
255
}
256
257
// Apply free-atom mask and set bias forces
258
AtomMatrix
biasForces = TADF.array() *
matter
->getFree().array();
259
matter
->setBiasForces(biasForces);
260
return
boostFact;
261
}
262
264
Matrix<double, Eigen::Dynamic, 1>
BondBoost::Rmdsteps
() {
265
Matrix<double, Eigen::Dynamic, 1> bondLengths(
nTABs
, 1);
266
long
count = 0;
267
268
// Boost-atom pairs
269
for
(
long
i = 0; i <
nBAs
; i++) {
270
for
(
long
j = i + 1; j <
nBAs
; j++) {
271
bondLengths(count, 0) =
matter
->distance(
BAList
[i],
BAList
[j]);
272
TABAList
[2 * count] =
BAList
[i];
273
TABAList
[2 * count + 1] =
BAList
[j];
274
count++;
275
}
276
}
277
278
// Boost-atom to rest-atom pairs
279
for
(
long
i = 0; i <
nBAs
; i++) {
280
for
(
long
j = 0; j <
nRAs
; j++) {
281
bondLengths(count, 0) =
matter
->distance(
BAList
[i],
RAList
[j]);
282
TABAList
[2 * count] =
BAList
[i];
283
TABAList
[2 * count + 1] =
RAList
[j];
284
count++;
285
}
286
}
287
288
if
(count !=
nTABs
) {
289
QUILL_LOG_DEBUG(
log
,
"Total involved bond count does not match expected\n"
);
290
}
291
return
bondLengths;
292
}
293
295
long
BondBoost::BondSelect
() {
296
const
double
qCutoff =
parameters
.hyperdynamics_options().qcut;
297
298
// Count bonds within cutoff
299
long
nSelected = 0;
300
for
(
long
i = 0; i <
nTABs
; i++) {
301
if
(
TABLList
(i, 0) <= qCutoff) {
302
nSelected++;
303
}
304
}
305
306
EBBLList
.setZero(nSelected, 1);
307
BBAList
.resize(2 * nSelected);
308
long
count = 0;
309
for
(
long
i = 0; i <
nTABs
; i++) {
310
if
(
TABLList
(i, 0) <= qCutoff) {
311
EBBLList
(count, 0) =
TABLList
(i, 0);
312
BBAList
[2 * count] =
TABAList
[2 * i];
313
BBAList
[2 * count + 1] =
TABAList
[2 * i + 1];
314
count++;
315
}
316
}
317
return
nSelected;
318
}
319
320
}
// namespace eonc
BondBoost.h
AtomMatrix
Eigen::Matrix< double, Eigen::Dynamic, 3, eOnStorageOrder > AtomMatrix
Definition
Eigen.h:37
EonLogger.h
HelperFunctions.h
eonc::BondBoost::boost
double boost()
Evaluate the current bias potential and write bias forces.
Definition
BondBoost.cpp:141
eonc::BondBoost::parameters
const Parameters & parameters
Reference to a structure outside the scope of the class containing runtime parameters.
Definition
BondBoost.h:53
eonc::BondBoost::nReg
long nReg
Definition
BondBoost.h:67
eonc::BondBoost::nBBs
long nBBs
Definition
BondBoost.h:68
eonc::BondBoost::matter
Matter * matter
Pointer to atom object outside the scope of the class.
Definition
BondBoost.h:51
eonc::BondBoost::nAtoms
long nAtoms
Number of free coordinates.
Definition
BondBoost.h:50
eonc::BondBoost::Booststeps
double Booststeps()
Compute bias potential and forces for bond-boost hyperdynamics.
Definition
BondBoost.cpp:164
eonc::BondBoost::nBAs
long nBAs
Definition
BondBoost.h:64
eonc::BondBoost::rmdSteps
long rmdSteps() const
Definition
BondBoost.cpp:104
eonc::BondBoost::nTABs
long nTABs
Definition
BondBoost.h:66
eonc::BondBoost::BondSelect
long BondSelect()
Select bonds within cutoff distance for boosting.
Definition
BondBoost.cpp:295
eonc::BondBoost::~BondBoost
~BondBoost()
Destructor.
eonc::BondBoost::EBBLList
Matrix< double, Eigen::Dynamic, 1 > EBBLList
Definition
BondBoost.h:62
eonc::BondBoost::log
eonc::log::Scoped log
Definition
BondBoost.h:69
eonc::BondBoost::initialize
void initialize()
Definition
BondBoost.cpp:42
eonc::BondBoost::BBAList
std::vector< long > BBAList
Definition
BondBoost.h:58
eonc::BondBoost::TABLList
Matrix< double, Eigen::Dynamic, 1 > TABLList
Definition
BondBoost.h:61
eonc::BondBoost::Epsr_Q
std::vector< double > Epsr_Q
Definition
BondBoost.h:59
eonc::BondBoost::nRAs
long nRAs
Definition
BondBoost.h:65
eonc::BondBoost::BondBoost
BondBoost(Matter *matt, const Parameters ¶ms)
Constructor to be used when a structure is minimized.
Definition
BondBoost.cpp:31
eonc::BondBoost::TABAList
std::vector< long > TABAList
Definition
BondBoost.h:57
eonc::BondBoost::BAList
std::vector< long > BAList
Definition
BondBoost.h:55
eonc::BondBoost::CBBLList
Matrix< double, Eigen::Dynamic, 1 > CBBLList
Definition
BondBoost.h:63
eonc::BondBoost::advance
void advance()
Advance the equilibration / boost schedule by one MD step.
Definition
BondBoost.cpp:112
eonc::BondBoost::Rmdsteps
Matrix< double, Eigen::Dynamic, 1 > Rmdsteps()
Measure all tagged-atom bond lengths for the equilibration phase.
Definition
BondBoost.cpp:264
eonc::BondBoost::RAList
std::vector< long > RAList
Definition
BondBoost.h:56
eonc::Hyperdynamics::BOND_BOOST
static const char BOND_BOOST[]
Definition
BondBoost.h:75
eonc::Hyperdynamics::NONE
static const char NONE[]
Definition
BondBoost.h:74
eonc::Matter
Definition
Matter.h:90
eonc::Parameters
Definition
Parameters.h:35
eonc::helpers::split_string_int
std::vector< int > split_string_int(std::string s, std::string delim)
Definition
HelperFunctions.cpp:329
eonc
RAII resource manager for the ARTn C library with global synchronization.
Definition
ARTnSaddleSearch.cpp:23
client
BondBoost.cpp
Generated by
1.17.0
Generated by
Doxygen 1.17.0
Analytics by
Antics
provided by
TurtleTech ehf