41
43
template<bool calculate_gradients>
42
cvm::real colvar::coordnum::switching_function (cvm::rvector const &r0_vec,
44
cvm::real colvar::coordnum::switching_function(cvm::rvector const &r0_vec,
48
cvm::rvector const diff = cvm::position_distance (A1.pos, A2.pos);
49
cvm::rvector const scal_diff (diff.x/r0_vec.x, diff.y/r0_vec.y, diff.z/r0_vec.z);
50
cvm::rvector const diff = cvm::position_distance(A1.pos, A2.pos);
51
cvm::rvector const scal_diff(diff.x/r0_vec.x, diff.y/r0_vec.y, diff.z/r0_vec.z);
50
52
cvm::real const l2 = scal_diff.norm2();
52
54
// Assume en and ed are even integers, and avoid sqrt in the following
53
55
int const en2 = en/2;
54
56
int const ed2 = ed/2;
56
cvm::real const xn = std::pow (l2, en2);
57
cvm::real const xd = std::pow (l2, ed2);
58
cvm::real const xn = std::pow(l2, en2);
59
cvm::real const xd = std::pow(l2, ed2);
58
60
cvm::real const func = (1.0-xn)/(1.0-xd);
60
62
if (calculate_gradients) {
61
63
cvm::real const dFdl2 = (1.0/(1.0-xd))*(en2*(xn/l2) - func*ed2*(xd/l2))*(-1.0);
62
cvm::rvector const dl2dx ((2.0/(r0_vec.x*r0_vec.x))*diff.x,
63
(2.0/(r0_vec.y*r0_vec.y))*diff.y,
64
(2.0/(r0_vec.z*r0_vec.z))*diff.z);
64
cvm::rvector const dl2dx((2.0/(r0_vec.x*r0_vec.x))*diff.x,
65
(2.0/(r0_vec.y*r0_vec.y))*diff.y,
66
(2.0/(r0_vec.z*r0_vec.z))*diff.z);
65
67
A1.grad += (-1.0)*dFdl2*dl2dx;
66
68
A2.grad += dFdl2*dl2dx;
73
colvar::coordnum::coordnum (std::string const &conf)
74
: distance (conf), b_anisotropic (false), b_group2_center_only (false)
75
colvar::coordnum::coordnum(std::string const &conf)
76
: distance(conf), b_anisotropic(false), b_group2_center_only(false)
76
78
function_type = "coordnum";
77
x.type (colvarvalue::type_scalar);
79
x.type(colvarvalue::type_scalar);
79
81
// group1 and group2 are already initialized by distance()
80
82
if (group1.b_dummy)
81
cvm::fatal_error ("Error: only group2 is allowed to be a dummy atom\n");
83
cvm::fatal_error("Error: only group2 is allowed to be a dummy atom\n");
84
86
// need to specify this explicitly because the distance() constructor
85
87
// has set it to true
86
88
b_inverse_gradients = false;
88
bool const b_scale = get_keyval (conf, "cutoff", r0,
89
cvm::real (4.0 * cvm::unit_angstrom()));
90
bool const b_scale = get_keyval(conf, "cutoff", r0,
91
cvm::real(4.0 * cvm::unit_angstrom()));
91
if (get_keyval (conf, "cutoff3", r0_vec,
92
cvm::rvector (4.0, 4.0, 4.0), parse_silent)) {
93
if (get_keyval(conf, "cutoff3", r0_vec,
94
cvm::rvector(4.0, 4.0, 4.0), parse_silent)) {
95
cvm::fatal_error ("Error: cannot specify \"scale\" and "
97
cvm::fatal_error("Error: cannot specify \"scale\" and "
96
98
"\"scale3\" at the same time.\n");
97
99
b_anisotropic = true;
98
100
// remove meaningless negative signs
101
103
if (r0_vec.z < 0.0) r0_vec.z *= -1.0;
104
get_keyval (conf, "expNumer", en, int (6) );
105
get_keyval (conf, "expDenom", ed, int (12));
106
get_keyval(conf, "expNumer", en, int(6) );
107
get_keyval(conf, "expDenom", ed, int(12));
107
109
if ( (en%2) || (ed%2) ) {
108
cvm::fatal_error ("Error: odd exponents provided, can only use even ones.\n");
110
cvm::fatal_error("Error: odd exponents provided, can only use even ones.\n");
111
get_keyval (conf, "group2CenterOnly", b_group2_center_only, group2.b_dummy);
113
get_keyval(conf, "group2CenterOnly", b_group2_center_only, group2.b_dummy);
115
117
colvar::coordnum::coordnum()
116
: b_anisotropic (false), b_group2_center_only (false)
118
: b_anisotropic(false), b_group2_center_only(false)
118
120
function_type = "coordnum";
119
x.type (colvarvalue::type_scalar);
121
x.type(colvarvalue::type_scalar);
167
169
if (b_anisotropic) {
168
170
for (cvm::atom_iter ai1 = group1.begin(); ai1 != group1.end(); ai1++)
169
switching_function<true> (r0_vec, en, ed, *ai1, group2_com_atom);
171
switching_function<true>(r0_vec, en, ed, *ai1, group2_com_atom);
171
173
for (cvm::atom_iter ai1 = group1.begin(); ai1 != group1.end(); ai1++)
172
switching_function<true> (r0, en, ed, *ai1, group2_com_atom);
174
switching_function<true>(r0, en, ed, *ai1, group2_com_atom);
175
group2.set_weighted_gradient (group2_com_atom.grad);
177
group2.set_weighted_gradient(group2_com_atom.grad);
179
181
if (b_anisotropic) {
180
182
for (cvm::atom_iter ai1 = group1.begin(); ai1 != group1.end(); ai1++)
181
183
for (cvm::atom_iter ai2 = group2.begin(); ai2 != group2.end(); ai2++) {
182
switching_function<true> (r0_vec, en, ed, *ai1, *ai2);
184
switching_function<true>(r0_vec, en, ed, *ai1, *ai2);
185
187
for (cvm::atom_iter ai1 = group1.begin(); ai1 != group1.end(); ai1++)
186
188
for (cvm::atom_iter ai2 = group2.begin(); ai2 != group2.end(); ai2++) {
187
switching_function<true> (r0, en, ed, *ai1, *ai2);
189
switching_function<true>(r0, en, ed, *ai1, *ai2);
192
// if (cvm::debug()) {
193
// for (size_t i = 0; i < group1.size(); i++) {
194
// cvm::log ("atom["+cvm::to_str (group1[i].id+1)+"] gradient: "+
195
// cvm::to_str (group1[i].grad)+"\n");
198
// for (size_t i = 0; i < group2.size(); i++) {
199
// cvm::log ("atom["+cvm::to_str (group2[i].id+1)+"] gradient: "+
200
// cvm::to_str (group2[i].grad)+"\n");
205
void colvar::coordnum::apply_force (colvarvalue const &force)
195
void colvar::coordnum::apply_force(colvarvalue const &force)
207
197
if (!group1.noforce)
208
group1.apply_colvar_force (force.real_value);
198
group1.apply_colvar_force(force.real_value);
210
200
if (!group2.noforce)
211
group2.apply_colvar_force (force.real_value);
201
group2.apply_colvar_force(force.real_value);
216
206
// h_bond member functions
218
colvar::h_bond::h_bond (std::string const &conf)
208
colvar::h_bond::h_bond(std::string const &conf)
221
211
if (cvm::debug())
222
cvm::log ("Initializing h_bond object.\n");
212
cvm::log("Initializing h_bond object.\n");
224
214
function_type = "h_bond";
225
x.type (colvarvalue::type_scalar);
215
x.type(colvarvalue::type_scalar);
227
217
int a_num, d_num;
228
get_keyval (conf, "acceptor", a_num, -1);
229
get_keyval (conf, "donor", d_num, -1);
218
get_keyval(conf, "acceptor", a_num, -1);
219
get_keyval(conf, "donor", d_num, -1);
231
221
if ( (a_num == -1) || (d_num == -1) ) {
232
cvm::fatal_error ("Error: either acceptor or donor undefined.\n");
222
cvm::fatal_error("Error: either acceptor or donor undefined.\n");
235
acceptor = cvm::atom (a_num);
236
donor = cvm::atom (d_num);
237
atom_groups.push_back (new cvm::atom_group);
238
atom_groups[0]->add_atom (acceptor);
239
atom_groups[0]->add_atom (donor);
225
cvm::atom acceptor = cvm::atom(a_num);
226
cvm::atom donor = cvm::atom(d_num);
227
atom_groups.push_back(new cvm::atom_group);
228
atom_groups[0]->add_atom(acceptor);
229
atom_groups[0]->add_atom(donor);
241
get_keyval (conf, "cutoff", r0, (3.3 * cvm::unit_angstrom()));
242
get_keyval (conf, "expNumer", en, 6);
243
get_keyval (conf, "expDenom", ed, 8);
231
get_keyval(conf, "cutoff", r0, (3.3 * cvm::unit_angstrom()));
232
get_keyval(conf, "expNumer", en, 6);
233
get_keyval(conf, "expDenom", ed, 8);
245
235
if ( (en%2) || (ed%2) ) {
246
cvm::fatal_error ("Error: odd exponents provided, can only use even ones.\n");
236
cvm::fatal_error("Error: odd exponents provided, can only use even ones.\n");
249
239
if (cvm::debug())
250
cvm::log ("Done initializing h_bond object.\n");
240
cvm::log("Done initializing h_bond object.\n");
254
colvar::h_bond::h_bond (cvm::atom const &acceptor_i,
255
cvm::atom const &donor_i,
256
cvm::real r0_i, int en_i, int ed_i)
257
: acceptor (acceptor_i),
259
r0 (r0_i), en (en_i), ed (ed_i)
244
colvar::h_bond::h_bond(cvm::atom const &acceptor,
245
cvm::atom const &donor,
246
cvm::real r0_i, int en_i, int ed_i)
247
: r0(r0_i), en(en_i), ed(ed_i)
261
249
function_type = "h_bond";
262
x.type (colvarvalue::type_scalar);
250
x.type(colvarvalue::type_scalar);
264
atom_groups.push_back (new cvm::atom_group);
265
atom_groups[0]->add_atom (acceptor);
266
atom_groups[0]->add_atom (donor);
252
atom_groups.push_back(new cvm::atom_group);
253
atom_groups[0]->add_atom(acceptor);
254
atom_groups[0]->add_atom(donor);
269
257
colvar::h_bond::h_bond()
272
260
function_type = "h_bond";
273
x.type (colvarvalue::type_scalar);
261
x.type(colvarvalue::type_scalar);
277
265
colvar::h_bond::~h_bond()
279
for (int i=0; i<atom_groups.size(); i++) {
280
delete atom_groups[i];
267
delete atom_groups[0];
285
271
void colvar::h_bond::calc_value()
287
x.real_value = colvar::coordnum::switching_function<false> (r0, en, ed, acceptor, donor);
273
x.real_value = colvar::coordnum::switching_function<false>(r0, en, ed, (*atom_groups[0])[0], (*atom_groups[0])[1]);
291
277
void colvar::h_bond::calc_gradients()
293
colvar::coordnum::switching_function<true> (r0, en, ed, acceptor, donor);
294
(*atom_groups[0])[0].grad = acceptor.grad;
295
(*atom_groups[0])[1].grad = donor.grad;
279
colvar::coordnum::switching_function<true>(r0, en, ed, (*atom_groups[0])[0], (*atom_groups[0])[1]);
299
void colvar::h_bond::apply_force (colvarvalue const &force)
283
void colvar::h_bond::apply_force(colvarvalue const &force)
301
acceptor.apply_force (force.real_value * acceptor.grad);
302
donor.apply_force (force.real_value * donor.grad);
285
(atom_groups[0])->apply_colvar_force(force);
308
colvar::selfcoordnum::selfcoordnum (std::string const &conf)
309
: distance (conf, false)
291
colvar::selfcoordnum::selfcoordnum(std::string const &conf)
292
: distance(conf, false)
311
294
function_type = "selfcoordnum";
312
x.type (colvarvalue::type_scalar);
295
x.type(colvarvalue::type_scalar);
314
297
// group1 is already initialized by distance()
330
313
colvar::selfcoordnum::selfcoordnum()
332
315
function_type = "selfcoordnum";
333
x.type (colvarvalue::type_scalar);
316
x.type(colvarvalue::type_scalar);
337
320
void colvar::selfcoordnum::calc_value()
339
322
x.real_value = 0.0;
341
for (size_t i = 0; i < group1.size() - 1; i++)
342
for (size_t j = i + 1; j < group1.size(); j++)
343
x.real_value += colvar::coordnum::switching_function<false> (r0, en, ed, group1[i], group1[j]);
323
for (size_t i = 0; i < group1.size() - 1; i++) {
324
for (size_t j = i + 1; j < group1.size(); j++) {
325
x.real_value += colvar::coordnum::switching_function<false>(r0, en, ed, group1[i], group1[j]);
347
331
void colvar::selfcoordnum::calc_gradients()
349
for (size_t i = 0; i < group1.size() - 1; i++)
350
for (size_t j = i + 1; j < group1.size(); j++)
351
colvar::coordnum::switching_function<true> (r0, en, ed, group1[i], group1[j]);
333
for (size_t i = 0; i < group1.size() - 1; i++) {
334
for (size_t j = i + 1; j < group1.size(); j++) {
335
colvar::coordnum::switching_function<true>(r0, en, ed, group1[i], group1[j]);
354
void colvar::selfcoordnum::apply_force (colvarvalue const &force)
340
void colvar::selfcoordnum::apply_force(colvarvalue const &force)
357
group1.apply_colvar_force (force.real_value);
342
if (!group1.noforce) {
343
group1.apply_colvar_force(force.real_value);