2 * This file is part of the GROMACS molecular simulation package.
4 * Copyright (c) 2014,2015,2016,2017,2018 by the GROMACS development team.
5 * Copyright (c) 2019,2020, by the GROMACS development team, led by
6 * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
7 * and including many others, as listed in the AUTHORS file in the
8 * top-level source directory and at http://www.gromacs.org.
10 * GROMACS is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public License
12 * as published by the Free Software Foundation; either version 2.1
13 * of the License, or (at your option) any later version.
15 * GROMACS is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with GROMACS; if not, see
22 * http://www.gnu.org/licenses, or write to the Free Software Foundation,
23 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
25 * If you want to redistribute modifications to GROMACS, please
26 * consider that scientific software is very special. Version
27 * control is crucial - bugs must be traceable. We will be happy to
28 * consider code for inclusion in the official distribution, but
29 * derived work must not be called official GROMACS. Details are found
30 * in the README & COPYING files - if they are missing, get the
31 * official version at http://www.gromacs.org.
33 * To help us fund GROMACS development, we humbly ask that you cite
34 * the research papers on the package. Check out http://www.gromacs.org.
38 * \brief This file defines functions for "pair" interactions
39 * (i.e. listed non-bonded interactions, e.g. 1-4 interactions)
41 * \author Mark Abraham <mark.j.abraham@gmail.com>
43 * \ingroup module_listed_forces
51 #include "gromacs/listed_forces/bonded.h"
52 #include "gromacs/math/functions.h"
53 #include "gromacs/math/vec.h"
54 #include "gromacs/mdtypes/group.h"
55 #include "gromacs/mdtypes/md_enums.h"
56 #include "gromacs/mdtypes/nblist.h"
57 #include "gromacs/mdtypes/simulation_workload.h"
58 #include "gromacs/pbcutil/ishift.h"
59 #include "gromacs/pbcutil/mshift.h"
60 #include "gromacs/pbcutil/pbc.h"
61 #include "gromacs/pbcutil/pbc_simd.h"
62 #include "gromacs/simd/simd.h"
63 #include "gromacs/simd/simd_math.h"
64 #include "gromacs/simd/vector_operations.h"
65 #include "gromacs/tables/forcetable.h"
66 #include "gromacs/utility/basedefinitions.h"
67 #include "gromacs/utility/fatalerror.h"
68 #include "gromacs/utility/gmxassert.h"
70 #include "listed_internal.h"
72 using namespace gmx; // TODO: Remove when this file is moved into gmx namespace
74 /*! \brief Issue a warning if a listed interaction is beyond a table limit */
75 static void warning_rlimit(const rvec* x, int ai, int aj, int* global_atom_index, real r, real rlimit)
78 "Listed nonbonded interaction between particles %d and %d\n"
79 "at distance %.3f which is larger than the table limit %.3f nm.\n\n"
80 "This is likely either a 1,4 interaction, or a listed interaction inside\n"
81 "a smaller molecule you are decoupling during a free energy calculation.\n"
82 "Since interactions at distances beyond the table cannot be computed,\n"
83 "they are skipped until they are inside the table limit again. You will\n"
84 "only see this message once, even if it occurs for several interactions.\n\n"
85 "IMPORTANT: This should not happen in a stable simulation, so there is\n"
86 "probably something wrong with your system. Only change the table-extension\n"
87 "distance in the mdp file if you are really sure that is the reason.\n",
88 glatnr(global_atom_index, ai), glatnr(global_atom_index, aj), r, rlimit);
93 "%8f %8f %8f\n%8f %8f %8f\n1-4 (%d,%d) interaction not within cut-off! r=%g. "
95 x[ai][XX], x[ai][YY], x[ai][ZZ], x[aj][XX], x[aj][YY], x[aj][ZZ],
96 glatnr(global_atom_index, ai), glatnr(global_atom_index, aj), r);
100 /*! \brief Compute the energy and force for a single pair interaction */
101 static real evaluate_single(real r2,
111 real rinv, r, rtab, eps, eps2, Y, F, Geps, Heps2, Fp, VVe, FFe, VVd, FFd, VVr, FFr, fscal;
114 /* Do the tabulated interactions - first table lookup */
115 rinv = gmx::invsqrt(r2);
118 ntab = static_cast<int>(rtab);
121 ntab = static_cast<int>(tableStride * ntab);
125 Geps = eps * vftab[ntab + 2];
126 Heps2 = eps2 * vftab[ntab + 3];
127 Fp = F + Geps + Heps2;
129 FFe = Fp + Geps + 2.0 * Heps2;
133 Geps = eps * vftab[ntab + 6];
134 Heps2 = eps2 * vftab[ntab + 7];
135 Fp = F + Geps + Heps2;
137 FFd = Fp + Geps + 2.0 * Heps2;
141 Geps = eps * vftab[ntab + 10];
142 Heps2 = eps2 * vftab[ntab + 11];
143 Fp = F + Geps + Heps2;
145 FFr = Fp + Geps + 2.0 * Heps2;
148 *vvdw = c6 * VVd + c12 * VVr;
150 fscal = -(qq * FFe + c6 * FFd + c12 * FFr) * tabscale * rinv;
155 /*! \brief Compute the energy and force for a single pair interaction under FEP */
156 static real free_energy_evaluate_single(real r2,
172 const real lfac_coul[2],
173 const real lfac_vdw[2],
174 const real dlfac_coul[2],
175 const real dlfac_vdw[2],
184 real rp, rpm2, rtab, eps, eps2, Y, F, Geps, Heps2, Fp, VV, FF, fscal;
185 real qq[2], c6[2], c12[2], sigma6[2], sigma2[2], sigma_pow[2];
186 real alpha_coul_eff, alpha_vdw_eff, dvdl_coul, dvdl_vdw;
187 real rpinv, r_coul, r_vdw, velecsum, vvdwsum;
188 real fscal_vdw[2], fscal_elec[2];
189 real velec[2], vvdw[2];
191 const real half = 0.5;
192 const real minusOne = -1.0;
193 const real one = 1.0;
194 const real two = 2.0;
195 const real six = 6.0;
196 const real fourtyeight = 48.0;
205 if (sc_r_power == six)
207 rpm2 = r2 * r2; /* r4 */
208 rp = rpm2 * r2; /* r6 */
210 else if (sc_r_power == fourtyeight)
212 rp = r2 * r2 * r2; /* r6 */
213 rp = rp * rp; /* r12 */
214 rp = rp * rp; /* r24 */
215 rp = rp * rp; /* r48 */
216 rpm2 = rp / r2; /* r46 */
220 rp = std::pow(r2, half * sc_r_power); /* not currently supported as input, but can handle it */
224 /* Loop over state A(0) and B(1) */
225 for (i = 0; i < 2; i++)
227 if ((c6[i] > 0) && (c12[i] > 0))
229 /* The c6 & c12 coefficients now contain the constants 6.0 and 12.0, respectively.
230 * Correct for this by multiplying with (1/12.0)/(1/6.0)=6.0/12.0=0.5.
232 sigma6[i] = half * c12[i] / c6[i];
233 sigma2[i] = std::cbrt(half * c12[i] / c6[i]);
234 /* should be able to get rid of this ^^^ internal pow call eventually. Will require agreement on
235 what data to store externally. Can't be fixed without larger scale changes, so not 5.0 */
236 if (sigma6[i] < sigma6_min) /* for disappearing coul and vdw with soft core at the same time */
238 sigma6[i] = sigma6_min;
239 sigma2[i] = sigma2_min;
244 sigma6[i] = sigma6_def;
245 sigma2[i] = sigma2_def;
247 if (sc_r_power == six)
249 sigma_pow[i] = sigma6[i];
251 else if (sc_r_power == fourtyeight)
253 sigma_pow[i] = sigma6[i] * sigma6[i]; /* sigma^12 */
254 sigma_pow[i] = sigma_pow[i] * sigma_pow[i]; /* sigma^24 */
255 sigma_pow[i] = sigma_pow[i] * sigma_pow[i]; /* sigma^48 */
258 { /* not really supported as input, but in here for testing the general case*/
259 sigma_pow[i] = std::pow(sigma2[i], sc_r_power / 2);
263 /* only use softcore if one of the states has a zero endstate - softcore is for avoiding infinities!*/
264 if ((c12[0] > 0) && (c12[1] > 0))
271 alpha_vdw_eff = alpha_vdw;
272 alpha_coul_eff = alpha_coul;
275 /* Loop over A and B states again */
276 for (i = 0; i < 2; i++)
283 /* Only spend time on A or B state if it is non-zero */
284 if ((qq[i] != 0) || (c6[i] != 0) || (c12[i] != 0))
287 rpinv = one / (alpha_coul_eff * lfac_coul[i] * sigma_pow[i] + rp);
288 r_coul = std::pow(rpinv, minusOne / sc_r_power);
290 /* Electrostatics table lookup data */
291 rtab = r_coul * tabscale;
292 ntab = static_cast<int>(rtab);
295 ntab = static_cast<int>(tableStride * ntab);
299 Geps = eps * vftab[ntab + 2];
300 Heps2 = eps2 * vftab[ntab + 3];
301 Fp = F + Geps + Heps2;
303 FF = Fp + Geps + two * Heps2;
304 velec[i] = qq[i] * VV;
305 fscal_elec[i] = -qq[i] * FF * r_coul * rpinv * tabscale;
308 rpinv = one / (alpha_vdw_eff * lfac_vdw[i] * sigma_pow[i] + rp);
309 r_vdw = std::pow(rpinv, minusOne / sc_r_power);
310 /* Vdw table lookup data */
311 rtab = r_vdw * tabscale;
312 ntab = static_cast<int>(rtab);
319 Geps = eps * vftab[ntab + 6];
320 Heps2 = eps2 * vftab[ntab + 7];
321 Fp = F + Geps + Heps2;
323 FF = Fp + Geps + two * Heps2;
324 vvdw[i] = c6[i] * VV;
325 fscal_vdw[i] = -c6[i] * FF;
330 Geps = eps * vftab[ntab + 10];
331 Heps2 = eps2 * vftab[ntab + 11];
332 Fp = F + Geps + Heps2;
334 FF = Fp + Geps + two * Heps2;
335 vvdw[i] += c12[i] * VV;
336 fscal_vdw[i] -= c12[i] * FF;
337 fscal_vdw[i] *= r_vdw * rpinv * tabscale;
340 /* Now we have velec[i], vvdw[i], and fscal[i] for both states */
341 /* Assemble A and B states */
347 for (i = 0; i < 2; i++)
349 velecsum += LFC[i] * velec[i];
350 vvdwsum += LFV[i] * vvdw[i];
352 fscal += (LFC[i] * fscal_elec[i] + LFV[i] * fscal_vdw[i]) * rpm2;
354 dvdl_coul += velec[i] * DLF[i]
355 + LFC[i] * alpha_coul_eff * dlfac_coul[i] * fscal_elec[i] * sigma_pow[i];
356 dvdl_vdw += vvdw[i] * DLF[i]
357 + LFV[i] * alpha_vdw_eff * dlfac_vdw[i] * fscal_vdw[i] * sigma_pow[i];
360 dvdl[efptCOUL] += dvdl_coul;
361 dvdl[efptVDW] += dvdl_vdw;
363 *velectot = velecsum;
369 /*! \brief Calculate pair interactions, supports all types and conditions. */
370 template<BondedKernelFlavor flavor>
371 static real do_pairs_general(int ftype,
373 const t_iatom iatoms[],
374 const t_iparams iparams[],
378 const struct t_pbc* pbc,
379 const struct t_graph* g,
383 const t_forcerec* fr,
384 gmx_grppairener_t* grppener,
385 int* global_atom_index)
390 int i, itype, ai, aj, gid;
393 real fscal, velec, vvdw;
394 real* energygrp_elec;
396 static gmx_bool warned_rlimit = FALSE;
397 /* Free energy stuff */
398 gmx_bool bFreeEnergy;
399 real LFC[2], LFV[2], DLF[2], lfac_coul[2], lfac_vdw[2], dlfac_coul[2], dlfac_vdw[2];
400 real qqB, c6B, c12B, sigma2_def, sigma2_min;
406 energygrp_elec = grppener->ener[egCOUL14].data();
407 energygrp_vdw = grppener->ener[egLJ14].data();
410 energygrp_elec = grppener->ener[egCOULSR].data();
411 energygrp_vdw = grppener->ener[egLJSR].data();
414 energygrp_elec = nullptr; /* Keep compiler happy */
415 energygrp_vdw = nullptr; /* Keep compiler happy */
416 gmx_fatal(FARGS, "Unknown function type %d in do_nonbonded14", ftype);
419 if (fr->efep != efepNO)
421 /* Lambda factor for state A=1-lambda and B=lambda */
422 LFC[0] = 1.0 - lambda[efptCOUL];
423 LFV[0] = 1.0 - lambda[efptVDW];
424 LFC[1] = lambda[efptCOUL];
425 LFV[1] = lambda[efptVDW];
427 /*derivative of the lambda factor for state A and B */
432 sigma2_def = std::cbrt(fr->sc_sigma6_def);
433 sigma2_min = std::cbrt(fr->sc_sigma6_min);
435 for (i = 0; i < 2; i++)
437 lfac_coul[i] = (fr->sc_power == 2 ? (1 - LFC[i]) * (1 - LFC[i]) : (1 - LFC[i]));
439 DLF[i] * fr->sc_power / fr->sc_r_power * (fr->sc_power == 2 ? (1 - LFC[i]) : 1);
440 lfac_vdw[i] = (fr->sc_power == 2 ? (1 - LFV[i]) * (1 - LFV[i]) : (1 - LFV[i]));
442 DLF[i] * fr->sc_power / fr->sc_r_power * (fr->sc_power == 2 ? (1 - LFV[i]) : 1);
447 sigma2_min = sigma2_def = 0;
450 /* TODO This code depends on the logic in tables.c that constructs
451 the table layout, which should be made explicit in future
455 "Pair-interaction code that uses GROMACS interaction tables supports exactly 3 tables");
457 fr->pairsTable->interaction == GMX_TABLE_INTERACTION_ELEC_VDWREP_VDWDISP,
458 "Pair interaction kernels need a table with Coulomb, repulsion and dispersion entries");
460 const real epsfac = fr->ic->epsfac;
463 for (i = 0; (i < nbonds);)
468 gid = GID(md->cENER[ai], md->cENER[aj], md->nenergrp);
474 bFreeEnergy = (fr->efep != efepNO
475 && (((md->nPerturbed != 0) && (md->bPerturbed[ai] || md->bPerturbed[aj]))
476 || iparams[itype].lj14.c6A != iparams[itype].lj14.c6B
477 || iparams[itype].lj14.c12A != iparams[itype].lj14.c12B));
478 qq = md->chargeA[ai] * md->chargeA[aj] * epsfac * fr->fudgeQQ;
479 c6 = iparams[itype].lj14.c6A;
480 c12 = iparams[itype].lj14.c12A;
483 qq = iparams[itype].ljc14.qi * iparams[itype].ljc14.qj * epsfac
484 * iparams[itype].ljc14.fqq;
485 c6 = iparams[itype].ljc14.c6;
486 c12 = iparams[itype].ljc14.c12;
489 qq = iparams[itype].ljcnb.qi * iparams[itype].ljcnb.qj * epsfac;
490 c6 = iparams[itype].ljcnb.c6;
491 c12 = iparams[itype].ljcnb.c12;
494 /* Cannot happen since we called gmx_fatal() above in this case */
495 qq = c6 = c12 = 0; /* Keep compiler happy */
499 /* To save flops in the optimized kernels, c6/c12 have 6.0/12.0 derivative prefactors
500 * included in the general nfbp array now. This means the tables are scaled down by the
501 * same factor, so when we use the original c6/c12 parameters from iparams[] they must
507 /* Do we need to apply full periodic boundary conditions? */
510 fshift_index = pbc_dx_aiuc(pbc, x[ai], x[aj], dx);
514 fshift_index = CENTRAL;
515 rvec_sub(x[ai], x[aj], dx);
519 if (r2 >= fr->pairsTable->r * fr->pairsTable->r)
521 /* This check isn't race free. But it doesn't matter because if a race occurs the only
522 * disadvantage is that the warning is printed twice */
525 warning_rlimit(x, ai, aj, global_atom_index, sqrt(r2), fr->pairsTable->r);
526 warned_rlimit = TRUE;
533 /* Currently free energy is only supported for F_LJ14, so no need to check for that if we got here */
534 qqB = md->chargeB[ai] * md->chargeB[aj] * epsfac * fr->fudgeQQ;
535 c6B = iparams[itype].lj14.c6B * 6.0;
536 c12B = iparams[itype].lj14.c12B * 12.0;
538 fscal = free_energy_evaluate_single(
539 r2, fr->sc_r_power, fr->sc_alphacoul, fr->sc_alphavdw, fr->pairsTable->scale,
540 fr->pairsTable->data, fr->pairsTable->stride, qq, c6, c12, qqB, c6B, c12B, LFC,
541 LFV, DLF, lfac_coul, lfac_vdw, dlfac_coul, dlfac_vdw, fr->sc_sigma6_def,
542 fr->sc_sigma6_min, sigma2_def, sigma2_min, &velec, &vvdw, dvdl);
546 /* Evaluate tabulated interaction without free energy */
547 fscal = evaluate_single(r2, fr->pairsTable->scale, fr->pairsTable->data,
548 fr->pairsTable->stride, qq, c6, c12, &velec, &vvdw);
551 energygrp_elec[gid] += velec;
552 energygrp_vdw[gid] += vvdw;
553 svmul(fscal, dx, dx);
559 if (computeVirial(flavor))
563 /* Correct the shift forces using the graph */
564 ivec_sub(SHIFT_IVEC(g, ai), SHIFT_IVEC(g, aj), dt);
565 fshift_index = IVEC2IS(dt);
567 if (fshift_index != CENTRAL)
569 rvec_inc(fshift[fshift_index], dx);
570 rvec_dec(fshift[CENTRAL], dx);
577 /*! \brief Calculate pairs, only for plain-LJ + plain Coulomb normal type.
579 * This function is templated for real/SimdReal and for optimization.
581 template<typename T, int pack_size, typename pbc_type>
582 static void do_pairs_simple(int nbonds,
583 const t_iatom iatoms[],
584 const t_iparams iparams[],
589 const real scale_factor)
591 const int nfa1 = 1 + 2;
597 #if GMX_SIMD_HAVE_REAL
598 alignas(GMX_SIMD_ALIGNMENT) std::int32_t ai[pack_size];
599 alignas(GMX_SIMD_ALIGNMENT) std::int32_t aj[pack_size];
600 alignas(GMX_SIMD_ALIGNMENT) real coeff[3 * pack_size];
602 std::int32_t ai[pack_size];
603 std::int32_t aj[pack_size];
604 real coeff[3 * pack_size];
607 /* nbonds is #pairs*nfa1, here we step pack_size pairs */
608 for (int i = 0; i < nbonds; i += pack_size * nfa1)
610 /* Collect atoms for pack_size pairs.
611 * iu indexes into iatoms, we should not let iu go beyond nbonds.
614 for (int s = 0; s < pack_size; s++)
616 int itype = iatoms[iu];
617 ai[s] = iatoms[iu + 1];
618 aj[s] = iatoms[iu + 2];
620 if (i + s * nfa1 < nbonds)
622 coeff[0 * pack_size + s] = iparams[itype].lj14.c6A;
623 coeff[1 * pack_size + s] = iparams[itype].lj14.c12A;
624 coeff[2 * pack_size + s] = md->chargeA[ai[s]] * md->chargeA[aj[s]];
626 /* Avoid indexing the iatoms array out of bounds.
627 * We pad the coordinate indices with the last atom pair.
629 if (iu + nfa1 < nbonds)
636 /* Pad the coefficient arrays with zeros to get zero forces */
637 coeff[0 * pack_size + s] = 0;
638 coeff[1 * pack_size + s] = 0;
639 coeff[2 * pack_size + s] = 0;
643 /* Load the coordinates */
645 gatherLoadUTranspose<3>(reinterpret_cast<const real*>(x), ai, &xi[XX], &xi[YY], &xi[ZZ]);
646 gatherLoadUTranspose<3>(reinterpret_cast<const real*>(x), aj, &xj[XX], &xj[YY], &xj[ZZ]);
648 T c6 = load<T>(coeff + 0 * pack_size);
649 T c12 = load<T>(coeff + 1 * pack_size);
650 T qq = load<T>(coeff + 2 * pack_size);
652 /* We could save these operations by storing 6*C6,12*C12 */
657 pbc_dx_aiuc(pbc, xi, xj, dr);
659 T rsq = dr[XX] * dr[XX] + dr[YY] * dr[YY] + dr[ZZ] * dr[ZZ];
660 T rinv = gmx::invsqrt(rsq);
661 T rinv2 = rinv * rinv;
662 T rinv6 = rinv2 * rinv2 * rinv2;
664 /* Calculate the Coulomb force * r */
665 T cfr = ef * qq * rinv;
667 /* Calculate the LJ force * r and add it to the Coulomb part */
668 T fr = gmx::fma(fms(c12, rinv6, c6), rinv6, cfr);
670 T finvr = fr * rinv2;
671 T fx = finvr * dr[XX];
672 T fy = finvr * dr[YY];
673 T fz = finvr * dr[ZZ];
675 /* Add the pair forces to the force array.
676 * Note that here we might add multiple force components for some atoms
677 * due to the SIMD padding. But the extra force components are zero.
679 transposeScatterIncrU<4>(reinterpret_cast<real*>(f), ai, fx, fy, fz);
680 transposeScatterDecrU<4>(reinterpret_cast<real*>(f), aj, fx, fy, fz);
684 /*! \brief Calculate all listed pair interactions */
685 void do_pairs(int ftype,
687 const t_iatom iatoms[],
688 const t_iparams iparams[],
692 const struct t_pbc* pbc,
693 const struct t_graph* g,
697 const t_forcerec* fr,
698 const bool havePerturbedInteractions,
699 const gmx::StepWorkload& stepWork,
700 gmx_grppairener_t* grppener,
701 int* global_atom_index)
703 if (ftype == F_LJ14 && fr->ic->vdwtype != evdwUSER && !EEL_USER(fr->ic->eeltype)
704 && !havePerturbedInteractions && (!stepWork.computeVirial && !stepWork.computeEnergy))
706 /* We use a fast code-path for plain LJ 1-4 without FEP.
708 * TODO: Add support for energies (straightforward) and virial
709 * in the SIMD template. For the virial it's inconvenient to store
710 * the force sums for the shifts and we should directly calculate
711 * and sum the virial for the shifts. But we should do this
712 * at once for the angles and dihedrals as well.
714 #if GMX_SIMD_HAVE_REAL
715 if (fr->use_simd_kernels)
717 alignas(GMX_SIMD_ALIGNMENT) real pbc_simd[9 * GMX_SIMD_REAL_WIDTH];
718 set_pbc_simd(pbc, pbc_simd);
720 do_pairs_simple<SimdReal, GMX_SIMD_REAL_WIDTH, const real*>(
721 nbonds, iatoms, iparams, x, f, pbc_simd, md, fr->ic->epsfac * fr->fudgeQQ);
726 /* This construct is needed because pbc_dx_aiuc doesn't accept pbc=NULL */
728 const t_pbc* pbc_nonnull;
736 set_pbc(&pbc_no, PbcType::No, nullptr);
737 pbc_nonnull = &pbc_no;
740 do_pairs_simple<real, 1, const t_pbc*>(nbonds, iatoms, iparams, x, f, pbc_nonnull, md,
741 fr->ic->epsfac * fr->fudgeQQ);
744 else if (stepWork.computeVirial)
746 do_pairs_general<BondedKernelFlavor::ForcesAndVirialAndEnergy>(
747 ftype, nbonds, iatoms, iparams, x, f, fshift, pbc, g, lambda, dvdl, md, fr,
748 grppener, global_atom_index);
752 do_pairs_general<BondedKernelFlavor::ForcesAndEnergy>(ftype, nbonds, iatoms, iparams, x, f,
753 fshift, pbc, g, lambda, dvdl, md, fr,
754 grppener, global_atom_index);