@@ -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+
166191template <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)) {
0 commit comments