2 * This file is part of the GROMACS molecular simulation package.
4 * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
5 * Copyright (c) 2001-2004, The GROMACS development team.
6 * Copyright (c) 2013,2014, by the GROMACS development team, led by
7 * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
8 * and including many others, as listed in the AUTHORS file in the
9 * top-level source directory and at http://www.gromacs.org.
11 * GROMACS is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Lesser General Public License
13 * as published by the Free Software Foundation; either version 2.1
14 * of the License, or (at your option) any later version.
16 * GROMACS is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * Lesser General Public License for more details.
21 * You should have received a copy of the GNU Lesser General Public
22 * License along with GROMACS; if not, see
23 * http://www.gnu.org/licenses, or write to the Free Software Foundation,
24 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
26 * If you want to redistribute modifications to GROMACS, please
27 * consider that scientific software is very special. Version
28 * control is crucial - bugs must be traceable. We will be happy to
29 * consider code for inclusion in the official distribution, but
30 * derived work must not be called official GROMACS. Details are found
31 * in the README & COPYING files - if they are missing, get the
32 * official version at http://www.gromacs.org.
34 * To help us fund GROMACS development, we humbly ask that you cite
35 * the research papers on the package. Check out http://www.gromacs.org.
43 #include "gromacs/legacyheaders/types/group.h"
44 #include "gromacs/listed-forces/bonded.h"
45 #include "gromacs/math/vec.h"
46 #include "gromacs/pbcutil/ishift.h"
47 #include "gromacs/pbcutil/mshift.h"
48 #include "gromacs/pbcutil/pbc.h"
49 #include "gromacs/utility/basedefinitions.h"
50 #include "gromacs/utility/fatalerror.h"
53 nb_listed_warning_rlimit(const rvec *x, int ai, int aj, int * global_atom_index, real r, real rlimit)
55 gmx_warning("Listed nonbonded interaction between particles %d and %d\n"
56 "at distance %.3f which is larger than the table limit %.3f nm.\n\n"
57 "This is likely either a 1,4 interaction, or a listed interaction inside\n"
58 "a smaller molecule you are decoupling during a free energy calculation.\n"
59 "Since interactions at distances beyond the table cannot be computed,\n"
60 "they are skipped until they are inside the table limit again. You will\n"
61 "only see this message once, even if it occurs for several interactions.\n\n"
62 "IMPORTANT: This should not happen in a stable simulation, so there is\n"
63 "probably something wrong with your system. Only change the table-extension\n"
64 "distance in the mdp file if you are really sure that is the reason.\n",
65 glatnr(global_atom_index, ai), glatnr(global_atom_index, aj), r, rlimit);
70 "%8f %8f %8f\n%8f %8f %8f\n1-4 (%d,%d) interaction not within cut-off! r=%g. Ignored\n",
71 x[ai][XX], x[ai][YY], x[ai][ZZ], x[aj][XX], x[aj][YY], x[aj][ZZ],
72 glatnr(global_atom_index, ai), glatnr(global_atom_index, aj), r);
78 /* This might logically belong better in the nb_generic.c module, but it is only
79 * used in do_nonbonded_listed(), and we want it to be inlined there to avoid an
80 * extra functional call for every single pair listed in the topology.
83 nb_evaluate_single(real r2, real tabscale, real *vftab,
84 real qq, real c6, real c12, real *velec, real *vvdw)
86 real rinv, r, rtab, eps, eps2, Y, F, Geps, Heps2, Fp, VVe, FFe, VVd, FFd, VVr, FFr, fscal;
89 /* Do the tabulated interactions - first table lookup */
90 rinv = gmx_invsqrt(r2);
100 Geps = eps*vftab[ntab+2];
101 Heps2 = eps2*vftab[ntab+3];
104 FFe = Fp+Geps+2.0*Heps2;
108 Geps = eps*vftab[ntab+6];
109 Heps2 = eps2*vftab[ntab+7];
112 FFd = Fp+Geps+2.0*Heps2;
116 Geps = eps*vftab[ntab+10];
117 Heps2 = eps2*vftab[ntab+11];
120 FFr = Fp+Geps+2.0*Heps2;
123 *vvdw = c6*VVd+c12*VVr;
125 fscal = -(qq*FFe+c6*FFd+c12*FFr)*tabscale*rinv;
131 nb_free_energy_evaluate_single(real r2, real sc_r_power, real alpha_coul, real alpha_vdw,
132 real tabscale, real *vftab,
133 real qqA, real c6A, real c12A, real qqB, real c6B, real c12B,
134 real LFC[2], real LFV[2], real DLF[2],
135 real lfac_coul[2], real lfac_vdw[2], real dlfac_coul[2], real dlfac_vdw[2],
136 real sigma6_def, real sigma6_min, real sigma2_def, real sigma2_min,
137 real *velectot, real *vvdwtot, real *dvdl)
139 real r, rp, rpm2, rtab, eps, eps2, Y, F, Geps, Heps2, Fp, VV, FF, fscal;
140 real qq[2], c6[2], c12[2], sigma6[2], sigma2[2], sigma_pow[2], sigma_powm2[2];
141 real alpha_coul_eff, alpha_vdw_eff, dvdl_coul, dvdl_vdw;
142 real rpinv, r_coul, r_vdw, velecsum, vvdwsum;
143 real fscal_vdw[2], fscal_elec[2];
144 real velec[2], vvdw[2];
147 const real half = 0.5;
148 const real one = 1.0;
149 const real two = 2.0;
150 const real six = 6.0;
151 const real fourtyeight = 48.0;
160 if (sc_r_power == six)
162 rpm2 = r2*r2; /* r4 */
163 rp = rpm2*r2; /* r6 */
165 else if (sc_r_power == fourtyeight)
167 rp = r2*r2*r2; /* r6 */
168 rp = rp*rp; /* r12 */
169 rp = rp*rp; /* r24 */
170 rp = rp*rp; /* r48 */
171 rpm2 = rp/r2; /* r46 */
175 rp = pow(r2, half*sc_r_power); /* not currently supported as input, but can handle it */
179 /* Loop over state A(0) and B(1) */
180 for (i = 0; i < 2; i++)
182 if ((c6[i] > 0) && (c12[i] > 0))
184 /* The c6 & c12 coefficients now contain the constants 6.0 and 12.0, respectively.
185 * Correct for this by multiplying with (1/12.0)/(1/6.0)=6.0/12.0=0.5.
187 sigma6[i] = half*c12[i]/c6[i];
188 sigma2[i] = pow(half*c12[i]/c6[i], 1.0/3.0);
189 /* should be able to get rid of this ^^^ internal pow call eventually. Will require agreement on
190 what data to store externally. Can't be fixed without larger scale changes, so not 5.0 */
191 if (sigma6[i] < sigma6_min) /* for disappearing coul and vdw with soft core at the same time */
193 sigma6[i] = sigma6_min;
194 sigma2[i] = sigma2_min;
199 sigma6[i] = sigma6_def;
200 sigma2[i] = sigma2_def;
202 if (sc_r_power == six)
204 sigma_pow[i] = sigma6[i];
205 sigma_powm2[i] = sigma6[i]/sigma2[i];
207 else if (sc_r_power == fourtyeight)
209 sigma_pow[i] = sigma6[i]*sigma6[i]; /* sigma^12 */
210 sigma_pow[i] = sigma_pow[i]*sigma_pow[i]; /* sigma^24 */
211 sigma_pow[i] = sigma_pow[i]*sigma_pow[i]; /* sigma^48 */
212 sigma_powm2[i] = sigma_pow[i]/sigma2[i];
215 { /* not really supported as input, but in here for testing the general case*/
216 sigma_pow[i] = pow(sigma2[i], sc_r_power/2);
217 sigma_powm2[i] = sigma_pow[i]/(sigma2[i]);
221 /* only use softcore if one of the states has a zero endstate - softcore is for avoiding infinities!*/
222 if ((c12[0] > 0) && (c12[1] > 0))
229 alpha_vdw_eff = alpha_vdw;
230 alpha_coul_eff = alpha_coul;
233 /* Loop over A and B states again */
234 for (i = 0; i < 2; i++)
241 /* Only spend time on A or B state if it is non-zero */
242 if ( (qq[i] != 0) || (c6[i] != 0) || (c12[i] != 0) )
245 rpinv = one/(alpha_coul_eff*lfac_coul[i]*sigma_pow[i]+rp);
246 r_coul = pow(rpinv, -one/sc_r_power);
248 /* Electrostatics table lookup data */
249 rtab = r_coul*tabscale;
257 Geps = eps*vftab[ntab+2];
258 Heps2 = eps2*vftab[ntab+3];
261 FF = Fp+Geps+two*Heps2;
263 fscal_elec[i] = -qq[i]*FF*r_coul*rpinv*tabscale;
266 rpinv = one/(alpha_vdw_eff*lfac_vdw[i]*sigma_pow[i]+rp);
267 r_vdw = pow(rpinv, -one/sc_r_power);
268 /* Vdw table lookup data */
269 rtab = r_vdw*tabscale;
277 Geps = eps*vftab[ntab+6];
278 Heps2 = eps2*vftab[ntab+7];
281 FF = Fp+Geps+two*Heps2;
283 fscal_vdw[i] = -c6[i]*FF;
288 Geps = eps*vftab[ntab+10];
289 Heps2 = eps2*vftab[ntab+11];
292 FF = Fp+Geps+two*Heps2;
293 vvdw[i] += c12[i]*VV;
294 fscal_vdw[i] -= c12[i]*FF;
295 fscal_vdw[i] *= r_vdw*rpinv*tabscale;
298 /* Now we have velec[i], vvdw[i], and fscal[i] for both states */
299 /* Assemble A and B states */
305 for (i = 0; i < 2; i++)
307 velecsum += LFC[i]*velec[i];
308 vvdwsum += LFV[i]*vvdw[i];
310 fscal += (LFC[i]*fscal_elec[i]+LFV[i]*fscal_vdw[i])*rpm2;
312 dvdl_coul += velec[i]*DLF[i] + LFC[i]*alpha_coul_eff*dlfac_coul[i]*fscal_elec[i]*sigma_pow[i];
313 dvdl_vdw += vvdw[i]*DLF[i] + LFV[i]*alpha_vdw_eff*dlfac_vdw[i]*fscal_vdw[i]*sigma_pow[i];
316 dvdl[efptCOUL] += dvdl_coul;
317 dvdl[efptVDW] += dvdl_vdw;
319 *velectot = velecsum;
326 do_nonbonded_listed(int ftype, int nbonds,
327 const t_iatom iatoms[], const t_iparams iparams[],
328 const rvec x[], rvec f[], rvec fshift[],
329 const t_pbc *pbc, const t_graph *g,
330 real *lambda, real *dvdl,
332 const t_forcerec *fr, gmx_grppairener_t *grppener,
333 int *global_atom_index)
339 int i, j, itype, ai, aj, gid;
342 real fscal, velec, vvdw;
343 real * energygrp_elec;
344 real * energygrp_vdw;
345 static gmx_bool warned_rlimit = FALSE;
346 /* Free energy stuff */
347 gmx_bool bFreeEnergy;
348 real LFC[2], LFV[2], DLF[2], lfac_coul[2], lfac_vdw[2], dlfac_coul[2], dlfac_vdw[2];
349 real qqB, c6B, c12B, sigma2_def, sigma2_min;
356 energygrp_elec = grppener->ener[egCOUL14];
357 energygrp_vdw = grppener->ener[egLJ14];
360 energygrp_elec = grppener->ener[egCOULSR];
361 energygrp_vdw = grppener->ener[egLJSR];
364 energygrp_elec = NULL; /* Keep compiler happy */
365 energygrp_vdw = NULL; /* Keep compiler happy */
366 gmx_fatal(FARGS, "Unknown function type %d in do_nonbonded14", ftype);
370 if (fr->efep != efepNO)
372 /* Lambda factor for state A=1-lambda and B=lambda */
373 LFC[0] = 1.0 - lambda[efptCOUL];
374 LFV[0] = 1.0 - lambda[efptVDW];
375 LFC[1] = lambda[efptCOUL];
376 LFV[1] = lambda[efptVDW];
378 /*derivative of the lambda factor for state A and B */
383 sigma2_def = pow(fr->sc_sigma6_def, 1.0/3.0);
384 sigma2_min = pow(fr->sc_sigma6_min, 1.0/3.0);
386 for (i = 0; i < 2; i++)
388 lfac_coul[i] = (fr->sc_power == 2 ? (1-LFC[i])*(1-LFC[i]) : (1-LFC[i]));
389 dlfac_coul[i] = DLF[i]*fr->sc_power/fr->sc_r_power*(fr->sc_power == 2 ? (1-LFC[i]) : 1);
390 lfac_vdw[i] = (fr->sc_power == 2 ? (1-LFV[i])*(1-LFV[i]) : (1-LFV[i]));
391 dlfac_vdw[i] = DLF[i]*fr->sc_power/fr->sc_r_power*(fr->sc_power == 2 ? (1-LFV[i]) : 1);
396 sigma2_min = sigma2_def = 0;
400 for (i = 0; (i < nbonds); )
405 gid = GID(md->cENER[ai], md->cENER[aj], md->nenergrp);
412 (fr->efep != efepNO &&
413 ((md->nPerturbed && (md->bPerturbed[ai] || md->bPerturbed[aj])) ||
414 iparams[itype].lj14.c6A != iparams[itype].lj14.c6B ||
415 iparams[itype].lj14.c12A != iparams[itype].lj14.c12B));
416 qq = md->chargeA[ai]*md->chargeA[aj]*fr->epsfac*fr->fudgeQQ;
417 c6 = iparams[itype].lj14.c6A;
418 c12 = iparams[itype].lj14.c12A;
421 qq = iparams[itype].ljc14.qi*iparams[itype].ljc14.qj*fr->epsfac*iparams[itype].ljc14.fqq;
422 c6 = iparams[itype].ljc14.c6;
423 c12 = iparams[itype].ljc14.c12;
426 qq = iparams[itype].ljcnb.qi*iparams[itype].ljcnb.qj*fr->epsfac;
427 c6 = iparams[itype].ljcnb.c6;
428 c12 = iparams[itype].ljcnb.c12;
431 /* Cannot happen since we called gmx_fatal() above in this case */
432 qq = c6 = c12 = 0; /* Keep compiler happy */
436 /* To save flops in the optimized kernels, c6/c12 have 6.0/12.0 derivative prefactors
437 * included in the general nfbp array now. This means the tables are scaled down by the
438 * same factor, so when we use the original c6/c12 parameters from iparams[] they must
444 /* Do we need to apply full periodic boundary conditions? */
445 if (fr->bMolPBC == TRUE)
447 fshift_index = pbc_dx_aiuc(pbc, x[ai], x[aj], dx);
451 fshift_index = CENTRAL;
452 rvec_sub(x[ai], x[aj], dx);
456 if (r2 >= fr->tab14.r*fr->tab14.r)
458 /* This check isn't race free. But it doesn't matter because if a race occurs the only
459 * disadvantage is that the warning is printed twice */
460 if (warned_rlimit == FALSE)
462 nb_listed_warning_rlimit(x, ai, aj, global_atom_index, sqrt(r2), fr->tab14.r);
463 warned_rlimit = TRUE;
470 /* Currently free energy is only supported for F_LJ14, so no need to check for that if we got here */
471 qqB = md->chargeB[ai]*md->chargeB[aj]*fr->epsfac*fr->fudgeQQ;
472 c6B = iparams[itype].lj14.c6B*6.0;
473 c12B = iparams[itype].lj14.c12B*12.0;
475 fscal = nb_free_energy_evaluate_single(r2, fr->sc_r_power, fr->sc_alphacoul, fr->sc_alphavdw,
476 fr->tab14.scale, fr->tab14.data, qq, c6, c12, qqB, c6B, c12B,
477 LFC, LFV, DLF, lfac_coul, lfac_vdw, dlfac_coul, dlfac_vdw,
478 fr->sc_sigma6_def, fr->sc_sigma6_min, sigma2_def, sigma2_min, &velec, &vvdw, dvdl);
482 /* Evaluate tabulated interaction without free energy */
483 fscal = nb_evaluate_single(r2, fr->tab14.scale, fr->tab14.data, qq, c6, c12, &velec, &vvdw);
486 energygrp_elec[gid] += velec;
487 energygrp_vdw[gid] += vvdw;
488 svmul(fscal, dx, dx);
496 /* Correct the shift forces using the graph */
497 ivec_sub(SHIFT_IVEC(g, ai), SHIFT_IVEC(g, aj), dt);
498 fshift_index = IVEC2IS(dt);
500 if (fshift_index != CENTRAL)
502 rvec_inc(fshift[fshift_index], dx);
503 rvec_dec(fshift[CENTRAL], dx);