Skip to content

Commit 64f214c

Browse files
committed
opt: Skip computation of switching function if the distance is too high for given tolerance
1 parent 2b62240 commit 64f214c

File tree

2 files changed

+44
-6
lines changed

2 files changed

+44
-6
lines changed

src/colvarcomp_coordnums.cpp

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,7 @@ int colvar::coordnum::init(std::string const &conf)
140140
get_keyval(conf, "tolerance", tolerance, tolerance);
141141
if (tolerance > 0) {
142142
cvm::main()->cite_feature("coordNum pairlist");
143+
compute_tolerance_l2_max();
143144
get_keyval(conf, "pairListFrequency", pairlist_freq, pairlist_freq);
144145
if ( ! (pairlist_freq > 0) ) {
145146
return cvm::error("Error: non-positive pairlistfrequency provided.\n",
@@ -163,6 +164,30 @@ colvar::coordnum::~coordnum()
163164
}
164165

165166

167+
void colvar::coordnum::compute_tolerance_l2_max()
168+
{
169+
cvm::real l2 = 1.001;
170+
cvm::real F = 0.0;
171+
cvm::real dFdl2 = 0.0;
172+
constexpr size_t num_iters_max = 1000000;
173+
constexpr cvm::real result_tol = 1.0e-6;
174+
constexpr cvm::real dF_tol = 1.0e-9;
175+
size_t i;
176+
// Find the value of l2 such that F(l2) = 0 using the Newton method
177+
for (i = 0; i < num_iters_max; i++) {
178+
F = switching_function<ef_use_pairlist | ef_gradients>(l2, dFdl2, en, ed, tolerance);
179+
if ((std::fabs(F) < result_tol) || (std::fabs(dFdl2) < dF_tol)) {
180+
break;
181+
}
182+
l2 -= F / dFdl2;
183+
}
184+
tolerance_l2_max = l2;
185+
if (cvm::debug()) {
186+
cvm::log("Found max valid l2 in " + cvm::to_str(i+1) + " iterations, result = " + cvm::to_str(l2) + " f(result) = " + cvm::to_str(F));
187+
}
188+
}
189+
190+
166191
template <bool use_group1_com, bool use_group2_com, int flags> void colvar::coordnum::main_loop(bool **pairlist_elem)
167192
{
168193
size_t const group1_num_coords = use_group1_com ? 1 : group1->size();
@@ -200,7 +225,7 @@ template <bool use_group1_com, bool use_group2_com, int flags> void colvar::coor
200225
compute_pair_coordnum<flags>(inv_r0_vec, inv_r0sq_vec, en, ed,
201226
x1, y1, z1, x2, y2, z2,
202227
gx1, gy1, gz1, gx2, gy2, gz2,
203-
tolerance) :
228+
tolerance, tolerance_l2_max) :
204229
0.0;
205230

206231
if ((flags & ef_use_pairlist) && (flags & ef_rebuild_pairlist)) {
@@ -410,7 +435,7 @@ void colvar::h_bond::calc_value()
410435
atom_groups[0]->grad_x(1),
411436
atom_groups[0]->grad_y(1),
412437
atom_groups[0]->grad_z(1),
413-
0.0);
438+
0.0, 1.0e20);
414439
// Skip the gradient
415440
}
416441

@@ -441,7 +466,7 @@ void colvar::h_bond::calc_gradients()
441466
atom_groups[0]->grad_x(1),
442467
atom_groups[0]->grad_y(1),
443468
atom_groups[0]->grad_z(1),
444-
0.0);
469+
0.0, 1.0e20);
445470
}
446471

447472

@@ -468,7 +493,7 @@ template<int flags> void colvar::selfcoordnum::selfcoordnum_sequential_loop(bool
468493
group1->pos_x(j), group1->pos_y(j), group1->pos_z(j),
469494
group1->grad_x(i), group1->grad_y(i), group1->grad_z(i),
470495
group1->grad_x(j), group1->grad_y(j), group1->grad_z(j),
471-
tolerance) :
496+
tolerance, tolerance_l2_max) :
472497
0.0;
473498

474499
if ((flags & ef_use_pairlist) && (flags & ef_rebuild_pairlist)) {

src/colvarcomp_coordnums.h

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ class colvar::coordnum : public colvar::cvc {
5454
const cvm::real a2x, const cvm::real a2y, const cvm::real a2z,
5555
cvm::real &g1x, cvm::real &g1y, cvm::real &g1z,
5656
cvm::real &g2x, cvm::real &g2y, cvm::real &g2z,
57-
cvm::real pairlist_tol);
57+
cvm::real pairlist_tol, cvm::real pairlist_tol_l2_max);
5858

5959
/// Workhorse function
6060
template <bool use_group1_com, bool use_group2_com, int flags> int compute_coordnum();
@@ -97,6 +97,12 @@ class colvar::coordnum : public colvar::cvc {
9797
/// Tolerance for the pair list
9898
cvm::real tolerance = 0.0;
9999

100+
/// Value of the squared scaled distance (l^2) that matches the given tolerance
101+
cvm::real tolerance_l2_max = 1.0e20;
102+
103+
/// Recompute the value of tolerance_l2_max
104+
void compute_tolerance_l2_max();
105+
100106
/// Frequency of update of the pair list
101107
int pairlist_freq = 100;
102108

@@ -234,7 +240,8 @@ cvm::real colvar::coordnum::compute_pair_coordnum(cvm::rvector const &inv_r0_vec
234240
cvm::real& g2x,
235241
cvm::real& g2y,
236242
cvm::real& g2z,
237-
cvm::real pairlist_tol)
243+
cvm::real pairlist_tol,
244+
cvm::real pairlist_tol_l2_max)
238245
{
239246
const cvm::atom_pos pos1{a1x, a1y, a1z};
240247
const cvm::atom_pos pos2{a2x, a2y, a2z};
@@ -243,6 +250,12 @@ cvm::real colvar::coordnum::compute_pair_coordnum(cvm::rvector const &inv_r0_vec
243250
diff.y * inv_r0_vec.y,
244251
diff.z * inv_r0_vec.z);
245252
cvm::real const l2 = scal_diff.norm2();
253+
if (flags & ef_use_pairlist) {
254+
if (l2 > pairlist_tol_l2_max) {
255+
// Exit if the distance is such that F(l2) < pairlist_tol
256+
return 0.0;
257+
}
258+
}
246259

247260
cvm::real dFdl2 = 0.0;
248261
cvm::real F = switching_function<flags>(l2, dFdl2, en, ed, pairlist_tol);

0 commit comments

Comments
 (0)