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,2015,2016,2017,2018,2019, 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.
39 #include "nb_free_energy.h"
45 #include "gromacs/gmxlib/nrnb.h"
46 #include "gromacs/gmxlib/nonbonded/nb_kernel.h"
47 #include "gromacs/gmxlib/nonbonded/nonbonded.h"
48 #include "gromacs/math/functions.h"
49 #include "gromacs/math/vec.h"
50 #include "gromacs/mdtypes/forcerec.h"
51 #include "gromacs/mdtypes/md_enums.h"
52 #include "gromacs/utility/fatalerror.h"
55 //! Enum for templating the soft-core treatment in the kernel
56 enum class SoftCoreTreatment
58 None
, //!< No soft-core
59 RPower6
, //!< Soft-core with r-power = 6
60 RPower48
//!< Soft-core with r-power = 48
63 //! Most treatments are fine with float in mixed-precision mode.
64 template <SoftCoreTreatment softCoreTreatment
>
67 //! Real type for soft-core calculations
71 //! This treatment requires double precision for some computations.
73 struct SoftCoreReal
<SoftCoreTreatment::RPower48
>
75 //! Real type for soft-core calculations
79 //! Computes r^(1/p) and 1/r^(1/p) for the standard p=6
80 template <SoftCoreTreatment softCoreTreatment
>
81 static inline void pthRoot(const real r
,
85 *invPthRoot
= gmx::invsqrt(std::cbrt(r
));
86 *pthRoot
= 1/(*invPthRoot
);
89 // We need a double version to make the specialization below work
91 //! Computes r^(1/p) and 1/r^(1/p) for the standard p=6
92 template <SoftCoreTreatment softCoreTreatment
>
93 static inline void pthRoot(const double r
,
97 *invPthRoot
= gmx::invsqrt(std::cbrt(r
));
98 *pthRoot
= 1/(*invPthRoot
);
102 //! Computes r^(1/p) and 1/r^(1/p) for p=48
104 inline void pthRoot
<SoftCoreTreatment::RPower48
>(const double r
,
108 *pthRoot
= std::pow(r
, 1.0/48.0);
109 *invPthRoot
= 1/(*pthRoot
);
112 //! Templated free-energy non-bonded kernel
113 template<SoftCoreTreatment softCoreTreatment
, bool scLambdasOrAlphasDiffer
>
115 nb_free_energy_kernel(const t_nblist
* gmx_restrict nlist
,
116 rvec
* gmx_restrict xx
,
117 rvec
* gmx_restrict ff
,
118 t_forcerec
* gmx_restrict fr
,
119 const t_mdatoms
* gmx_restrict mdatoms
,
120 nb_kernel_data_t
* gmx_restrict kernel_data
,
121 t_nrnb
* gmx_restrict nrnb
)
123 using SCReal
= typename SoftCoreReal
<softCoreTreatment
>::Real
;
125 constexpr bool useSoftCore
= (softCoreTreatment
!= SoftCoreTreatment::None
);
130 int i
, n
, ii
, is3
, ii3
, k
, nj0
, nj1
, jnr
, j3
, ggid
;
132 real tx
, ty
, tz
, Fscal
;
133 SCReal FscalC
[NSTATES
], FscalV
[NSTATES
]; /* Needs double for sc_power==48 */
134 SCReal Vcoul
[NSTATES
], Vvdw
[NSTATES
]; /* Needs double for sc_power==48 */
137 real qq
[NSTATES
], vctot
;
138 int ntiA
, ntiB
, tj
[NSTATES
];
139 real Vvdw6
, Vvdw12
, vvtot
;
140 real ix
, iy
, iz
, fix
, fiy
, fiz
;
141 real dx
, dy
, dz
, rsq
, rinv
;
142 real c6
[NSTATES
], c12
[NSTATES
], c6grid
;
143 real LFC
[NSTATES
], LFV
[NSTATES
], DLF
[NSTATES
];
144 SCReal dvdl_coul
, dvdl_vdw
;
145 real lfac_coul
[NSTATES
], dlfac_coul
[NSTATES
], lfac_vdw
[NSTATES
], dlfac_vdw
[NSTATES
];
146 real sigma6
[NSTATES
], alpha_vdw_eff
, alpha_coul_eff
;
147 SCReal rp
, rpm2
, rC
, rV
, rinvC
, rpinvC
, rinvV
, rpinvV
; /* Needs double for sc_power==48 */
148 real sigma_pow
[NSTATES
];
160 const real
* shiftvec
;
164 const real
* chargeA
;
165 const real
* chargeB
;
166 real sigma6_min
, sigma6_def
, lam_power
;
167 real alpha_coul
, alpha_vdw
, lambda_coul
, lambda_vdw
;
168 const real
* nbfp
, *nbfp_grid
;
172 gmx_bool bDoForces
, bDoShiftForces
, bDoPotential
;
173 gmx_bool bEwald
, bEwaldLJ
;
175 const real
* tab_ewald_F_lj
= nullptr;
176 const real
* tab_ewald_V_lj
= nullptr;
178 real vdw_swV3
, vdw_swV4
, vdw_swV5
, vdw_swF2
, vdw_swF3
, vdw_swF4
;
179 gmx_bool bComputeVdwInteraction
, bComputeElecInteraction
;
180 const real
* ewtab
= nullptr;
182 real ewrt
, eweps
, ewtabscale
= 0, ewtabhalfspace
= 0, sh_ewald
= 0;
184 const real onetwelfth
= 1.0/12.0;
185 const real onesixth
= 1.0/6.0;
186 const real zero
= 0.0;
187 const real half
= 0.5;
188 const real one
= 1.0;
189 const real two
= 2.0;
190 const real six
= 6.0;
192 /* Extract pointer to non-bonded interaction constants */
193 const interaction_const_t
*ic
= fr
->ic
;
198 fshift
= fr
->fshift
[0];
202 jindex
= nlist
->jindex
;
204 shift
= nlist
->shift
;
207 shiftvec
= fr
->shift_vec
[0];
208 chargeA
= mdatoms
->chargeA
;
209 chargeB
= mdatoms
->chargeB
;
210 Vc
= kernel_data
->energygrp_elec
;
211 typeA
= mdatoms
->typeA
;
212 typeB
= mdatoms
->typeB
;
215 nbfp_grid
= fr
->ljpme_c6grid
;
216 Vv
= kernel_data
->energygrp_vdw
;
217 lambda_coul
= kernel_data
->lambda
[efptCOUL
];
218 lambda_vdw
= kernel_data
->lambda
[efptVDW
];
219 dvdl
= kernel_data
->dvdl
;
220 alpha_coul
= fr
->sc_alphacoul
;
221 alpha_vdw
= fr
->sc_alphavdw
;
222 lam_power
= fr
->sc_power
;
223 sigma6_def
= fr
->sc_sigma6_def
;
224 sigma6_min
= fr
->sc_sigma6_min
;
225 bDoForces
= ((kernel_data
->flags
& GMX_NONBONDED_DO_FORCE
) != 0);
226 bDoShiftForces
= ((kernel_data
->flags
& GMX_NONBONDED_DO_SHIFTFORCE
) != 0);
227 bDoPotential
= ((kernel_data
->flags
& GMX_NONBONDED_DO_POTENTIAL
) != 0);
229 // Extract data from interaction_const_t
230 const real facel
= ic
->epsfac
;
231 const real rcoulomb
= ic
->rcoulomb
;
232 const real krf
= ic
->k_rf
;
233 const real crf
= ic
->c_rf
;
234 const real sh_lj_ewald
= ic
->sh_lj_ewald
;
235 const real rvdw
= ic
->rvdw
;
236 const real dispersionShift
= ic
->dispersion_shift
.cpot
;
237 const real repulsionShift
= ic
->repulsion_shift
.cpot
;
239 // Note that the nbnxm kernels do not support Coulomb potential switching at all
240 GMX_ASSERT(ic
->coulomb_modifier
!= eintmodPOTSWITCH
,
241 "Potential switching is not supported for Coulomb with FEP");
243 if (ic
->vdw_modifier
== eintmodPOTSWITCH
)
245 d
= ic
->rvdw
- ic
->rvdw_switch
;
246 vdw_swV3
= -10.0/(d
*d
*d
);
247 vdw_swV4
= 15.0/(d
*d
*d
*d
);
248 vdw_swV5
= -6.0/(d
*d
*d
*d
*d
);
249 vdw_swF2
= -30.0/(d
*d
*d
);
250 vdw_swF3
= 60.0/(d
*d
*d
*d
);
251 vdw_swF4
= -30.0/(d
*d
*d
*d
*d
);
255 /* Avoid warnings from stupid compilers (looking at you, Clang!) */
256 vdw_swV3
= vdw_swV4
= vdw_swV5
= vdw_swF2
= vdw_swF3
= vdw_swF4
= 0.0;
259 if (EVDW_PME(ic
->vdwtype
))
261 ivdw
= GMX_NBKERNEL_VDW_LJEWALD
;
265 ivdw
= GMX_NBKERNEL_VDW_LENNARDJONES
;
268 if (ic
->eeltype
== eelCUT
|| EEL_RF(ic
->eeltype
))
270 icoul
= GMX_NBKERNEL_ELEC_REACTIONFIELD
;
272 else if (EEL_PME_EWALD(ic
->eeltype
))
274 icoul
= GMX_NBKERNEL_ELEC_EWALD
;
278 gmx_incons("Unsupported eeltype with Verlet and free-energy");
281 rcutoff_max2
= std::max(ic
->rcoulomb
, ic
->rvdw
);
282 rcutoff_max2
= rcutoff_max2
*rcutoff_max2
;
284 bEwald
= (icoul
== GMX_NBKERNEL_ELEC_EWALD
);
285 bEwaldLJ
= (ivdw
== GMX_NBKERNEL_VDW_LJEWALD
);
287 if (bEwald
|| bEwaldLJ
)
289 const auto &tables
= *ic
->coulombEwaldTables
;
290 sh_ewald
= ic
->sh_ewald
;
291 ewtab
= tables
.tableFDV0
.data();
292 ewtabscale
= tables
.scale
;
293 ewtabhalfspace
= half
/ewtabscale
;
294 tab_ewald_F_lj
= tables
.tableF
.data();
295 tab_ewald_V_lj
= tables
.tableV
.data();
298 /* For Ewald/PME interactions we cannot easily apply the soft-core component to
299 * reciprocal space. When we use non-switched Ewald interactions, we
300 * assume the soft-coring does not significantly affect the grid contribution
301 * and apply the soft-core only to the full 1/r (- shift) pair contribution.
303 * However, we cannot use this approach for switch-modified since we would then
304 * effectively end up evaluating a significantly different interaction here compared to the
305 * normal (non-free-energy) kernels, either by applying a cutoff at a different
306 * position than what the user requested, or by switching different
307 * things (1/r rather than short-range Ewald). For these settings, we just
308 * use the traditional short-range Ewald interaction in that case.
310 GMX_RELEASE_ASSERT(!(bEwald
&& ic
->coulomb_modifier
== eintmodPOTSWITCH
) &&
311 !(bEwaldLJ
&& ic
->vdw_modifier
== eintmodPOTSWITCH
),
312 "Can not apply soft-core to switched Ewald potentials");
317 /* Lambda factor for state A, 1-lambda*/
318 LFC
[STATE_A
] = one
- lambda_coul
;
319 LFV
[STATE_A
] = one
- lambda_vdw
;
321 /* Lambda factor for state B, lambda*/
322 LFC
[STATE_B
] = lambda_coul
;
323 LFV
[STATE_B
] = lambda_vdw
;
325 /*derivative of the lambda factor for state A and B */
329 constexpr real sc_r_power
= (softCoreTreatment
== SoftCoreTreatment::RPower48
? 48.0_real
: 6.0_real
);
330 for (i
= 0; i
< NSTATES
; i
++)
332 lfac_coul
[i
] = (lam_power
== 2 ? (1-LFC
[i
])*(1-LFC
[i
]) : (1-LFC
[i
]));
333 dlfac_coul
[i
] = DLF
[i
]*lam_power
/sc_r_power
*(lam_power
== 2 ? (1-LFC
[i
]) : 1);
334 lfac_vdw
[i
] = (lam_power
== 2 ? (1-LFV
[i
])*(1-LFV
[i
]) : (1-LFV
[i
]));
335 dlfac_vdw
[i
] = DLF
[i
]*lam_power
/sc_r_power
*(lam_power
== 2 ? (1-LFV
[i
]) : 1);
338 for (n
= 0; (n
< nri
); n
++)
340 int npair_within_cutoff
;
342 npair_within_cutoff
= 0;
346 shY
= shiftvec
[is3
+1];
347 shZ
= shiftvec
[is3
+2];
355 iqA
= facel
*chargeA
[ii
];
356 iqB
= facel
*chargeB
[ii
];
357 ntiA
= 2*ntype
*typeA
[ii
];
358 ntiB
= 2*ntype
*typeB
[ii
];
365 for (k
= nj0
; (k
< nj1
); k
++)
372 rsq
= dx
*dx
+ dy
*dy
+ dz
*dz
;
374 if (rsq
>= rcutoff_max2
)
376 /* We save significant time by skipping all code below.
377 * Note that with soft-core interactions, the actual cut-off
378 * check might be different. But since the soft-core distance
379 * is always larger than r, checking on r here is safe.
383 npair_within_cutoff
++;
387 /* Note that unlike in the nbnxn kernels, we do not need
388 * to clamp the value of rsq before taking the invsqrt
389 * to avoid NaN in the LJ calculation, since here we do
390 * not calculate LJ interactions when C6 and C12 are zero.
393 rinv
= gmx::invsqrt(rsq
);
398 /* The force at r=0 is zero, because of symmetry.
399 * But note that the potential is in general non-zero,
400 * since the soft-cored r will be non-zero.
406 if (softCoreTreatment
== SoftCoreTreatment::None
)
408 /* The soft-core power p will not affect the results
409 * with not using soft-core, so we use power of 0 which gives
410 * the simplest math and cheapest code.
415 if (softCoreTreatment
== SoftCoreTreatment::RPower6
)
417 rpm2
= rsq
*rsq
; /* r4 */
418 rp
= rpm2
*rsq
; /* r6 */
420 if (softCoreTreatment
== SoftCoreTreatment::RPower48
)
422 rp
= rsq
*rsq
*rsq
; /* r6 */
423 rp
= rp
*rp
; /* r12 */
424 rp
= rp
*rp
; /* r24 */
425 rp
= rp
*rp
; /* r48 */
426 rpm2
= rp
/rsq
; /* r46 */
431 qq
[STATE_A
] = iqA
*chargeA
[jnr
];
432 qq
[STATE_B
] = iqB
*chargeB
[jnr
];
434 tj
[STATE_A
] = ntiA
+2*typeA
[jnr
];
435 tj
[STATE_B
] = ntiB
+2*typeB
[jnr
];
437 if (nlist
->excl_fep
== nullptr || nlist
->excl_fep
[k
])
439 c6
[STATE_A
] = nbfp
[tj
[STATE_A
]];
440 c6
[STATE_B
] = nbfp
[tj
[STATE_B
]];
442 for (i
= 0; i
< NSTATES
; i
++)
444 c12
[i
] = nbfp
[tj
[i
]+1];
447 if ((c6
[i
] > 0) && (c12
[i
] > 0))
449 /* c12 is stored scaled with 12.0 and c6 is scaled with 6.0 - correct for this */
450 sigma6
[i
] = half
*c12
[i
]/c6
[i
];
451 if (sigma6
[i
] < sigma6_min
) /* for disappearing coul and vdw with soft core at the same time */
453 sigma6
[i
] = sigma6_min
;
458 sigma6
[i
] = sigma6_def
;
460 if (softCoreTreatment
== SoftCoreTreatment::RPower6
)
462 sigma_pow
[i
] = sigma6
[i
];
466 sigma_pow
[i
] = sigma6
[i
]*sigma6
[i
]; /* sigma^12 */
467 sigma_pow
[i
] = sigma_pow
[i
]*sigma_pow
[i
]; /* sigma^24 */
468 sigma_pow
[i
] = sigma_pow
[i
]*sigma_pow
[i
]; /* sigma^48 */
475 /* only use softcore if one of the states has a zero endstate - softcore is for avoiding infinities!*/
476 if ((c12
[STATE_A
] > 0) && (c12
[STATE_B
] > 0))
483 alpha_vdw_eff
= alpha_vdw
;
484 alpha_coul_eff
= alpha_coul
;
488 for (i
= 0; i
< NSTATES
; i
++)
495 /* Only spend time on A or B state if it is non-zero */
496 if ( (qq
[i
] != 0) || (c6
[i
] != 0) || (c12
[i
] != 0) )
498 /* this section has to be inside the loop because of the dependence on sigma_pow */
501 rpinvC
= one
/(alpha_coul_eff
*lfac_coul
[i
]*sigma_pow
[i
]+rp
);
502 pthRoot
<softCoreTreatment
>(rpinvC
, &rinvC
, &rC
);
504 if (scLambdasOrAlphasDiffer
)
506 rpinvV
= one
/(alpha_vdw_eff
*lfac_vdw
[i
]*sigma_pow
[i
]+rp
);
507 pthRoot
<softCoreTreatment
>(rpinvV
, &rinvV
, &rV
);
511 /* We can avoid one expensive pow and one / operation */
528 /* Only process the coulomb interactions if we have charges,
529 * and if we either include all entries in the list (no cutoff
530 * used in the kernel), or if we are within the cutoff.
532 bComputeElecInteraction
=
533 ( bEwald
&& r
< rcoulomb
) ||
534 (!bEwald
&& rC
< rcoulomb
);
536 if ( (qq
[i
] != 0) && bComputeElecInteraction
)
540 /* Ewald FEP is done only on the 1/r part */
541 Vcoul
[i
] = qq
[i
]*(rinvC
-sh_ewald
);
542 FscalC
[i
] = qq
[i
]*rinvC
;
547 Vcoul
[i
] = qq
[i
]*(rinvC
+ krf
*rC
*rC
-crf
);
548 FscalC
[i
] = qq
[i
]*(rinvC
- two
*krf
*rC
*rC
);
552 /* Only process the VDW interactions if we have
553 * some non-zero parameters, and if we either
554 * include all entries in the list (no cutoff used
555 * in the kernel), or if we are within the cutoff.
557 bComputeVdwInteraction
=
558 ( bEwaldLJ
&& r
< rvdw
) ||
559 (!bEwaldLJ
&& rV
< rvdw
);
560 if ((c6
[i
] != 0 || c12
[i
] != 0) && bComputeVdwInteraction
)
562 /* cutoff LJ, also handles part of Ewald LJ */
563 if (softCoreTreatment
== SoftCoreTreatment::RPower6
)
570 rinv6
= rinv6
*rinv6
*rinv6
;
573 Vvdw12
= c12
[i
]*rinv6
*rinv6
;
575 Vvdw
[i
] = ( (Vvdw12
+ c12
[i
]*repulsionShift
)*onetwelfth
576 - (Vvdw6
+ c6
[i
]*dispersionShift
)*onesixth
);
577 FscalV
[i
] = Vvdw12
- Vvdw6
;
581 /* Subtract the grid potential at the cut-off */
582 c6grid
= nbfp_grid
[tj
[i
]];
583 Vvdw
[i
] += c6grid
*sh_lj_ewald
*onesixth
;
586 if (ic
->vdw_modifier
== eintmodPOTSWITCH
)
588 d
= rV
- ic
->rvdw_switch
;
589 d
= (d
> zero
) ? d
: zero
;
591 sw
= one
+d2
*d
*(vdw_swV3
+d
*(vdw_swV4
+d
*vdw_swV5
));
592 dsw
= d2
*(vdw_swF2
+d
*(vdw_swF3
+d
*vdw_swF4
));
594 FscalV
[i
] = FscalV
[i
]*sw
- rV
*Vvdw
[i
]*dsw
;
597 FscalV
[i
] = (rV
< rvdw
) ? FscalV
[i
] : zero
;
598 Vvdw
[i
] = (rV
< rvdw
) ? Vvdw
[i
] : zero
;
602 /* FscalC (and FscalV) now contain: dV/drC * rC
603 * Now we multiply by rC^-p, so it will be: dV/drC * rC^1-p
604 * Further down we first multiply by r^p-2 and then by
605 * the vector r, which in total gives: dV/drC * (r/rC)^1-p
612 /* Assemble A and B states */
613 for (i
= 0; i
< NSTATES
; i
++)
615 vctot
+= LFC
[i
]*Vcoul
[i
];
616 vvtot
+= LFV
[i
]*Vvdw
[i
];
618 Fscal
+= LFC
[i
]*FscalC
[i
]*rpm2
;
619 Fscal
+= LFV
[i
]*FscalV
[i
]*rpm2
;
623 dvdl_coul
+= Vcoul
[i
]*DLF
[i
] + LFC
[i
]*alpha_coul_eff
*dlfac_coul
[i
]*FscalC
[i
]*sigma_pow
[i
];
624 dvdl_vdw
+= Vvdw
[i
]*DLF
[i
] + LFV
[i
]*alpha_vdw_eff
*dlfac_vdw
[i
]*FscalV
[i
]*sigma_pow
[i
];
628 dvdl_coul
+= Vcoul
[i
]*DLF
[i
];
629 dvdl_vdw
+= Vvdw
[i
]*DLF
[i
];
633 else if (icoul
== GMX_NBKERNEL_ELEC_REACTIONFIELD
)
635 /* For excluded pairs, which are only in this pair list when
636 * using the Verlet scheme, we don't use soft-core.
637 * The group scheme also doesn't soft-core for these.
638 * As there is no singularity, there is no need for soft-core.
648 for (i
= 0; i
< NSTATES
; i
++)
650 vctot
+= LFC
[i
]*qq
[i
]*VV
;
651 Fscal
+= LFC
[i
]*qq
[i
]*FF
;
652 dvdl_coul
+= DLF
[i
]*qq
[i
]*VV
;
656 if (bEwald
&& r
< rcoulomb
)
658 /* See comment in the preamble. When using Ewald interactions
659 * (unless we use a switch modifier) we subtract the reciprocal-space
660 * Ewald component here which made it possible to apply the free
661 * energy interaction to 1/r (vanilla coulomb short-range part)
662 * above. This gets us closer to the ideal case of applying
663 * the softcore to the entire electrostatic interaction,
664 * including the reciprocal-space component.
669 ewitab
= static_cast<int>(ewrt
);
672 f_lr
= ewtab
[ewitab
]+eweps
*ewtab
[ewitab
+1];
673 v_lr
= (ewtab
[ewitab
+2]-ewtabhalfspace
*eweps
*(ewtab
[ewitab
]+f_lr
));
676 /* Note that any possible Ewald shift has already been applied in
677 * the normal interaction part above.
682 /* If we get here, the i particle (ii) has itself (jnr)
683 * in its neighborlist. This can only happen with the Verlet
684 * scheme, and corresponds to a self-interaction that will
685 * occur twice. Scale it down by 50% to only include it once.
690 for (i
= 0; i
< NSTATES
; i
++)
692 vctot
-= LFC
[i
]*qq
[i
]*v_lr
;
693 Fscal
-= LFC
[i
]*qq
[i
]*f_lr
;
694 dvdl_coul
-= (DLF
[i
]*qq
[i
])*v_lr
;
698 if (bEwaldLJ
&& r
< rvdw
)
700 /* See comment in the preamble. When using LJ-Ewald interactions
701 * (unless we use a switch modifier) we subtract the reciprocal-space
702 * Ewald component here which made it possible to apply the free
703 * energy interaction to r^-6 (vanilla LJ6 short-range part)
704 * above. This gets us closer to the ideal case of applying
705 * the softcore to the entire VdW interaction,
706 * including the reciprocal-space component.
708 /* We could also use the analytical form here
709 * iso a table, but that can cause issues for
710 * r close to 0 for non-interacting pairs.
715 rs
= rsq
*rinv
*ewtabscale
;
716 ri
= static_cast<int>(rs
);
718 f_lr
= (1 - frac
)*tab_ewald_F_lj
[ri
] + frac
*tab_ewald_F_lj
[ri
+1];
719 /* TODO: Currently the Ewald LJ table does not contain
720 * the factor 1/6, we should add this.
723 VV
= (tab_ewald_V_lj
[ri
] - ewtabhalfspace
*frac
*(tab_ewald_F_lj
[ri
] + f_lr
))/six
;
727 /* If we get here, the i particle (ii) has itself (jnr)
728 * in its neighborlist. This can only happen with the Verlet
729 * scheme, and corresponds to a self-interaction that will
730 * occur twice. Scale it down by 50% to only include it once.
735 for (i
= 0; i
< NSTATES
; i
++)
737 c6grid
= nbfp_grid
[tj
[i
]];
738 vvtot
+= LFV
[i
]*c6grid
*VV
;
739 Fscal
+= LFV
[i
]*c6grid
*FF
;
740 dvdl_vdw
+= (DLF
[i
]*c6grid
)*VV
;
752 /* OpenMP atomics are expensive, but this kernels is also
753 * expensive, so we can take this hit, instead of using
754 * thread-local output buffers and extra reduction.
756 * All the OpenMP regions in this file are trivial and should
757 * not throw, so no need for try/catch.
768 /* The atomics below are expensive with many OpenMP threads.
769 * Here unperturbed i-particles will usually only have a few
770 * (perturbed) j-particles in the list. Thus with a buffered list
771 * we can skip a significant number of i-reductions with a check.
773 if (npair_within_cutoff
> 0)
789 fshift
[is3
+1] += fiy
;
791 fshift
[is3
+2] += fiz
;
805 dvdl
[efptCOUL
] += dvdl_coul
;
807 dvdl
[efptVDW
] += dvdl_vdw
;
809 /* Estimate flops, average for free energy stuff:
810 * 12 flops per outer iteration
811 * 150 flops per inner iteration
814 inc_nrnb(nrnb
, eNR_NBKERNEL_FREE_ENERGY
, nlist
->nri
*12 + nlist
->jindex
[n
]*150);
817 void gmx_nb_free_energy_kernel(const t_nblist
*nlist
,
821 const t_mdatoms
*mdatoms
,
822 nb_kernel_data_t
*kernel_data
,
825 if (fr
->sc_alphacoul
== 0 && fr
->sc_alphavdw
== 0)
827 nb_free_energy_kernel
<SoftCoreTreatment::None
, false>(nlist
, xx
, ff
, fr
, mdatoms
, kernel_data
, nrnb
);
829 else if (fr
->sc_r_power
== 6.0_real
)
831 if (kernel_data
->lambda
[efptCOUL
] == kernel_data
->lambda
[efptVDW
] &&
832 fr
->sc_alphacoul
== fr
->sc_alphavdw
)
834 nb_free_energy_kernel
<SoftCoreTreatment::RPower6
, false>(nlist
, xx
, ff
, fr
, mdatoms
, kernel_data
, nrnb
);
838 nb_free_energy_kernel
<SoftCoreTreatment::RPower6
, true>(nlist
, xx
, ff
, fr
, mdatoms
, kernel_data
, nrnb
);
841 else if (fr
->sc_r_power
== 48.0_real
)
843 nb_free_energy_kernel
<SoftCoreTreatment::RPower48
, true>(nlist
, xx
, ff
, fr
, mdatoms
, kernel_data
, nrnb
);
847 GMX_RELEASE_ASSERT(false, "Unsupported soft-core r-power");