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 * check out http://www.gromacs.org for more information.
7 * Copyright (c) 2012, by the GROMACS development team, led by
8 * David van der Spoel, Berk Hess, Erik Lindahl, and including many
9 * others, as listed in the AUTHORS file in the top-level source
10 * directory and at http://www.gromacs.org.
12 * GROMACS is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU Lesser General Public License
14 * as published by the Free Software Foundation; either version 2.1
15 * of the License, or (at your option) any later version.
17 * GROMACS is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * Lesser General Public License for more details.
22 * You should have received a copy of the GNU Lesser General Public
23 * License along with GROMACS; if not, see
24 * http://www.gnu.org/licenses, or write to the Free Software Foundation,
25 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
27 * If you want to redistribute modifications to GROMACS, please
28 * consider that scientific software is very special. Version
29 * control is crucial - bugs must be traceable. We will be happy to
30 * consider code for inclusion in the official distribution, but
31 * derived work must not be called official GROMACS. Details are found
32 * in the README & COPYING files - if they are missing, get the
33 * official version at http://www.gromacs.org.
35 * To help us fund GROMACS development, we humbly ask that you cite
36 * the research papers on the package. Check out http://www.gromacs.org.
46 #include "nonbonded.h"
47 #include "nb_kernel.h"
51 gmx_nb_free_energy_kernel(t_nblist * nlist,
56 nb_kernel_data_t * kernel_data,
63 int i,j,n,ii,is3,ii3,k,nj0,nj1,jnr,j3,ggid;
65 real Fscal,FscalC[NSTATES],FscalV[NSTATES],tx,ty,tz;
66 real Vcoul[NSTATES],Vvdw[NSTATES];
67 real rinv6,r,rt,rtC,rtV;
69 real qq[NSTATES],vctot,krsq;
70 int ntiA,ntiB,tj[NSTATES];
71 real Vvdw6, Vvdw12,vvtot;
72 real ix,iy,iz,fix,fiy,fiz;
73 real dx,dy,dz,rsq,rinv;
74 real c6[NSTATES],c12[NSTATES];
75 real LFC[NSTATES],LFV[NSTATES],DLF[NSTATES];
76 double dvdl_coul,dvdl_vdw;
77 real lfac_coul[NSTATES],dlfac_coul[NSTATES],lfac_vdw[NSTATES],dlfac_vdw[NSTATES];
78 real sigma6[NSTATES],alpha_vdw_eff,alpha_coul_eff,sigma2_def,sigma2_min;
79 real rp,rpm2,rC,rV,rinvC,rpinvC,rinvV,rpinvV;
80 real sigma2[NSTATES],sigma_pow[NSTATES],sigma_powm2[NSTATES],rs,rs2;
81 int do_coultab,do_vdwtab,do_tab,tab_elemsize;
83 real Y,F,G,H,Fp,Geps,Heps2,epsC,eps2C,epsV,eps2V,VV,FF;
104 real sigma6_min,sigma6_def,lam_power,sc_power,sc_r_power;
105 real alpha_coul,alpha_vdw,lambda_coul,lambda_vdw,ewc;
111 real rcoulomb,rvdw,factor_coul,factor_vdw,sh_invrc6;
112 gmx_bool bExactElecCutoff,bExactVdwCutoff;
113 real rcutoff,rcutoff2,rswitch,d,d2,swV3,swV4,swV5,swF2,swF3,swF4,sw,dsw,rinvcorr;
118 fshift = fr->fshift[0];
119 Vc = kernel_data->energygrp_elec;
120 Vv = kernel_data->energygrp_vdw;
121 tabscale = kernel_data->table_elec_vdw->scale;
122 VFtab = kernel_data->table_elec_vdw->data;
126 jindex = nlist->jindex;
128 icoul = nlist->ielec;
130 shift = nlist->shift;
133 shiftvec = fr->shift_vec[0];
134 chargeA = mdatoms->chargeA;
135 chargeB = mdatoms->chargeB;
139 ewc = fr->ewaldcoeff;
140 Vc = kernel_data->energygrp_elec;
141 typeA = mdatoms->typeA;
142 typeB = mdatoms->typeB;
145 Vv = kernel_data->energygrp_vdw;
146 tabscale = kernel_data->table_elec_vdw->scale;
147 VFtab = kernel_data->table_elec_vdw->data;
148 lambda_coul = kernel_data->lambda[efptCOUL];
149 lambda_vdw = kernel_data->lambda[efptVDW];
150 dvdl = kernel_data->dvdl;
151 alpha_coul = fr->sc_alphacoul;
152 alpha_vdw = fr->sc_alphavdw;
153 lam_power = fr->sc_power;
154 sc_r_power = fr->sc_r_power;
155 sigma6_def = fr->sc_sigma6_def;
156 sigma6_min = fr->sc_sigma6_min;
157 bDoForces = kernel_data->flags & GMX_NONBONDED_DO_FORCE;
159 rcoulomb = fr->rcoulomb;
161 sh_invrc6 = fr->ic->sh_invrc6;
163 if(fr->coulomb_modifier==eintmodPOTSWITCH || fr->vdw_modifier==eintmodPOTSWITCH)
165 rcutoff = (fr->coulomb_modifier==eintmodPOTSWITCH) ? fr->rcoulomb : fr->rvdw;
166 rcutoff2 = rcutoff*rcutoff;
167 rswitch = (fr->coulomb_modifier==eintmodPOTSWITCH) ? fr->rcoulomb_switch : fr->rvdw_switch;
169 swV3 = -10.0/(d*d*d);
170 swV4 = 15.0/(d*d*d*d);
171 swV5 = -6.0/(d*d*d*d*d);
172 swF2 = -30.0/(d*d*d);
173 swF3 = 60.0/(d*d*d*d);
174 swF4 = -30.0/(d*d*d*d*d);
178 /* Stupid compilers dont realize these variables will not be used */
188 bExactElecCutoff = (fr->coulomb_modifier!=eintmodNONE) || fr->eeltype == eelRF_ZERO;
189 bExactVdwCutoff = (fr->vdw_modifier!=eintmodNONE);
191 /* fix compiler warnings */
200 /* Lambda factor for state A, 1-lambda*/
201 LFC[STATE_A] = 1.0 - lambda_coul;
202 LFV[STATE_A] = 1.0 - lambda_vdw;
204 /* Lambda factor for state B, lambda*/
205 LFC[STATE_B] = lambda_coul;
206 LFV[STATE_B] = lambda_vdw;
208 /*derivative of the lambda factor for state A and B */
212 for (i=0;i<NSTATES;i++)
214 lfac_coul[i] = (lam_power==2 ? (1-LFC[i])*(1-LFC[i]) : (1-LFC[i]));
215 dlfac_coul[i] = DLF[i]*lam_power/sc_r_power*(lam_power==2 ? (1-LFC[i]) : 1);
216 lfac_vdw[i] = (lam_power==2 ? (1-LFV[i])*(1-LFV[i]) : (1-LFV[i]));
217 dlfac_vdw[i] = DLF[i]*lam_power/sc_r_power*(lam_power==2 ? (1-LFV[i]) : 1);
220 sigma2_def = pow(sigma6_def,1.0/3.0);
221 sigma2_min = pow(sigma6_min,1.0/3.0);
223 /* Ewald (not PME) table is special (icoul==enbcoulFEWALD) */
225 do_coultab = (icoul==GMX_NBKERNEL_ELEC_CUBICSPLINETABLE);
226 do_vdwtab = (ivdw==GMX_NBKERNEL_VDW_CUBICSPLINETABLE);
228 do_tab = do_coultab || do_vdwtab;
230 /* we always use the combined table here */
233 for(n=0; (n<nri); n++)
237 shY = shiftvec[is3+1];
238 shZ = shiftvec[is3+2];
246 iqA = facel*chargeA[ii];
247 iqB = facel*chargeB[ii];
248 ntiA = 2*ntype*typeA[ii];
249 ntiB = 2*ntype*typeB[ii];
256 for(k=nj0; (k<nj1); k++)
263 rsq = dx*dx+dy*dy+dz*dz;
264 rinv = gmx_invsqrt(rsq);
266 if (sc_r_power == 6.0)
268 rpm2 = rsq*rsq; /* r4 */
269 rp = rpm2*rsq; /* r6 */
271 else if (sc_r_power == 48.0)
273 rp = rsq*rsq*rsq; /* r6 */
274 rp = rp*rp; /* r12 */
275 rp = rp*rp; /* r24 */
276 rp = rp*rp; /* r48 */
277 rpm2 = rp/rsq; /* r46 */
281 rp = pow(r,sc_r_power); /* not currently supported as input, but can handle it */
285 tj[STATE_A] = ntiA+2*typeA[jnr];
286 tj[STATE_B] = ntiB+2*typeB[jnr];
287 qq[STATE_A] = iqA*chargeA[jnr];
288 qq[STATE_B] = iqB*chargeB[jnr];
290 for (i=0;i<NSTATES;i++)
294 c12[i] = nbfp[tj[i]+1];
295 if((c6[i] > 0) && (c12[i] > 0))
297 /* c12 is stored scaled with 12.0 and c6 is scaled with 6.0 - correct for this */
298 sigma6[i] = 0.5*c12[i]/c6[i];
299 sigma2[i] = pow(sigma6[i],1.0/3.0);
300 /* should be able to get rid of this ^^^ internal pow call eventually. Will require agreement on
301 what data to store externally. Can't be fixed without larger scale changes, so not 4.6 */
302 if (sigma6[i] < sigma6_min) { /* for disappearing coul and vdw with soft core at the same time */
303 sigma6[i] = sigma6_min;
304 sigma2[i] = sigma2_min;
309 sigma6[i] = sigma6_def;
310 sigma2[i] = sigma2_def;
312 if (sc_r_power == 6.0)
314 sigma_pow[i] = sigma6[i];
315 sigma_powm2[i] = sigma6[i]/sigma2[i];
317 else if (sc_r_power == 48.0)
319 sigma_pow[i] = sigma6[i]*sigma6[i]; /* sigma^12 */
320 sigma_pow[i] = sigma_pow[i]*sigma_pow[i]; /* sigma^24 */
321 sigma_pow[i] = sigma_pow[i]*sigma_pow[i]; /* sigma^48 */
322 sigma_powm2[i] = sigma_pow[i]/sigma2[i];
325 { /* not really supported as input, but in here for testing the general case*/
326 sigma_pow[i] = pow(sigma2[i],sc_r_power/2);
327 sigma_powm2[i] = sigma_pow[i]/(sigma2[i]);
331 /* only use softcore if one of the states has a zero endstate - softcore is for avoiding infinities!*/
332 if ((c12[STATE_A] > 0) && (c12[STATE_B] > 0)) {
336 alpha_vdw_eff = alpha_vdw;
337 alpha_coul_eff = alpha_coul;
340 for (i=0;i<NSTATES;i++)
347 /* Only spend time on A or B state if it is non-zero */
348 if( (qq[i] != 0) || (c6[i] != 0) || (c12[i] != 0) )
351 /* this section has to be inside the loop becaue of the dependence on sigma_pow */
352 rpinvC = 1.0/(alpha_coul_eff*lfac_coul[i]*sigma_pow[i]+rp);
353 rinvC = pow(rpinvC,1.0/sc_r_power);
356 rpinvV = 1.0/(alpha_vdw_eff*lfac_vdw[i]*sigma_pow[i]+rp);
357 rinvV = pow(rpinvV,1.0/sc_r_power);
360 factor_coul = (rC<=rcoulomb) ? 1.0 : 0.0;
361 factor_vdw = (rV<=rvdw) ? 1.0 : 0.0;
369 n1C = tab_elemsize*n0;
375 n1V = tab_elemsize*n0;
382 case GMX_NBKERNEL_ELEC_COULOMB:
383 case GMX_NBKERNEL_ELEC_EWALD:
384 /* simple cutoff (yes, ewald is done all on direct space for free energy) */
385 Vcoul[i] = qq[i]*rinvC;
386 FscalC[i] = Vcoul[i]*rpinvC;
389 case GMX_NBKERNEL_ELEC_REACTIONFIELD:
391 Vcoul[i] = qq[i]*(rinvC+krf*rC*rC-crf);
392 FscalC[i] = qq[i]*(rinvC*rpinvC-2.0*krf);
395 case GMX_NBKERNEL_ELEC_CUBICSPLINETABLE:
396 /* non-Ewald tabulated coulomb */
400 Geps = epsC*VFtab[nnn+2];
401 Heps2 = eps2C*VFtab[nnn+3];
404 FF = Fp+Geps+2.0*Heps2;
406 FscalC[i] = -qq[i]*tabscale*FF*rC*rpinvC;
415 if(fr->coulomb_modifier==eintmodPOTSWITCH)
418 d = (d>0.0) ? d : 0.0;
420 sw = 1.0+d2*d*(swV3+d*(swV4+d*swV5));
421 dsw = d2*(swF2+d*(swF3+d*swF4));
424 FscalC[i] = FscalC[i]*sw + Vcoul[i]*dsw;
429 FscalC[i] = (rC<rcoulomb) ? FscalC[i] : 0.0;
430 Vcoul[i] = (rC<rcoulomb) ? Vcoul[i] : 0.0;
434 if((c6[i] != 0) || (c12[i] != 0))
438 case GMX_NBKERNEL_VDW_LENNARDJONES:
440 if (sc_r_power == 6.0)
446 rinv6 = pow(rinvV,6.0);
449 Vvdw12 = c12[i]*rinv6*rinv6;
450 if(fr->vdw_modifier==eintmodPOTSHIFT)
452 Vvdw[i] = ( (Vvdw12-c12[i]*sh_invrc6*sh_invrc6)*(1.0/12.0)
453 -(Vvdw6-c6[i]*sh_invrc6)*(1.0/6.0));
457 Vvdw[i] = Vvdw12*(1.0/12.0)-Vvdw6*(1.0/6.0);
459 FscalV[i] = (Vvdw12-Vvdw6)*rpinvV;
462 case GMX_NBKERNEL_VDW_BUCKINGHAM:
463 gmx_fatal(FARGS,"Buckingham free energy not supported.");
466 case GMX_NBKERNEL_VDW_CUBICSPLINETABLE:
472 Geps = epsV*VFtab[nnn+2];
473 Heps2 = eps2V*VFtab[nnn+3];
476 FF = Fp+Geps+2.0*Heps2;
478 FscalV[i] -= c6[i]*tabscale*FF*rV*rpinvV;
483 Geps = epsV*VFtab[nnn+6];
484 Heps2 = eps2V*VFtab[nnn+7];
487 FF = Fp+Geps+2.0*Heps2;
488 Vvdw[i] += c12[i]*VV;
489 FscalV[i] -= c12[i]*tabscale*FF*rV*rpinvV;
498 if(fr->vdw_modifier==eintmodPOTSWITCH)
501 d = (d>0.0) ? d : 0.0;
503 sw = 1.0+d2*d*(swV3+d*(swV4+d*swV5));
504 dsw = d2*(swF2+d*(swF3+d*swF4));
507 FscalV[i] = FscalV[i]*sw + Vvdw[i]*dsw;
509 FscalV[i] = (rV<rvdw) ? FscalV[i] : 0.0;
510 Vvdw[i] = (rV<rvdw) ? Vvdw[i] : 0.0;
518 if (icoul==GMX_NBKERNEL_ELEC_EWALD)
520 /* because we compute the softcore normally,
521 we have to remove the ewald short range portion. Done outside of
522 the states loop because this part doesn't depend on the scaled R */
526 VV = gmx_erf(ewc*r)*rinv;
527 FF = rinv*rinv*(VV - ewc*M_2_SQRTPI*exp(-ewc*ewc*rsq));
535 for (i=0;i<NSTATES;i++)
537 vctot -= LFC[i]*qq[i]*VV;
538 Fscal -= LFC[i]*qq[i]*FF;
539 dvdl_coul -= (DLF[i]*qq[i])*VV;
543 /* Assemble A and B states */
544 for (i=0;i<NSTATES;i++)
546 vctot += LFC[i]*Vcoul[i];
547 vvtot += LFV[i]*Vvdw[i];
549 Fscal += LFC[i]*FscalC[i]*rpm2;
550 Fscal += LFV[i]*FscalV[i]*rpm2;
552 dvdl_coul += Vcoul[i]*DLF[i] + LFC[i]*alpha_coul_eff*dlfac_coul[i]*FscalC[i]*sigma_pow[i];
553 dvdl_vdw += Vvdw[i]*DLF[i] + LFV[i]*alpha_vdw_eff*dlfac_vdw[i]*FscalV[i]*sigma_pow[i];
565 f[j3+1] = f[j3+1] - ty;
566 f[j3+2] = f[j3+2] - tz;
572 f[ii3] = f[ii3] + fix;
573 f[ii3+1] = f[ii3+1] + fiy;
574 f[ii3+2] = f[ii3+2] + fiz;
575 fshift[is3] = fshift[is3] + fix;
576 fshift[is3+1] = fshift[is3+1] + fiy;
577 fshift[is3+2] = fshift[is3+2] + fiz;
580 Vc[ggid] = Vc[ggid] + vctot;
581 Vv[ggid] = Vv[ggid] + vvtot;
584 dvdl[efptCOUL] += dvdl_coul;
585 dvdl[efptVDW] += dvdl_vdw;
587 /* Estimate flops, average for free energy stuff:
588 * 12 flops per outer iteration
589 * 150 flops per inner iteration
591 inc_nrnb(nrnb,eNR_NBKERNEL_FREE_ENERGY,nlist->nri*12 + nlist->jindex[n]*150);
595 nb_free_energy_evaluate_single(real r2,real sc_r_power,real alpha_coul,real alpha_vdw,
596 real tabscale,real *vftab,
597 real qqA, real c6A, real c12A, real qqB, real c6B, real c12B,
598 real LFC[2], real LFV[2],real DLF[2],
599 real lfac_coul[2], real lfac_vdw[2],real dlfac_coul[2], real dlfac_vdw[2],
600 real sigma6_def, real sigma6_min,real sigma2_def, real sigma2_min,
601 real *velectot, real *vvdwtot, real *dvdl)
603 real r,rp,rpm2,rtab,eps,eps2,Y,F,Geps,Heps2,Fp,VV,FF,fscal;
604 real qq[2],c6[2],c12[2],sigma6[2],sigma2[2],sigma_pow[2],sigma_powm2[2];
605 real alpha_coul_eff,alpha_vdw_eff,dvdl_coul,dvdl_vdw;
606 real rpinv,r_coul,r_vdw,velecsum,vvdwsum;
607 real fscal_vdw[2],fscal_elec[2];
608 real velec[2],vvdw[2];
618 if (sc_r_power == 6.0)
620 rpm2 = r2*r2; /* r4 */
621 rp = rpm2*r2; /* r6 */
623 else if (sc_r_power == 48.0)
625 rp = r2*r2*r2; /* r6 */
626 rp = rp*rp; /* r12 */
627 rp = rp*rp; /* r24 */
628 rp = rp*rp; /* r48 */
629 rpm2 = rp/r2; /* r46 */
633 rp = pow(r2,0.5*sc_r_power); /* not currently supported as input, but can handle it */
637 /* Loop over state A(0) and B(1) */
640 if((c6[i] > 0) && (c12[i] > 0))
642 /* The c6 & c12 coefficients now contain the constants 6.0 and 12.0, respectively.
643 * Correct for this by multiplying with (1/12.0)/(1/6.0)=6.0/12.0=0.5.
645 sigma6[i] = 0.5*c12[i]/c6[i];
646 sigma2[i] = pow(0.5*c12[i]/c6[i],1.0/3.0);
647 /* should be able to get rid of this ^^^ internal pow call eventually. Will require agreement on
648 what data to store externally. Can't be fixed without larger scale changes, so not 4.6 */
649 if (sigma6[i] < sigma6_min) { /* for disappearing coul and vdw with soft core at the same time */
650 sigma6[i] = sigma6_min;
651 sigma2[i] = sigma2_min;
656 sigma6[i] = sigma6_def;
657 sigma2[i] = sigma2_def;
659 if (sc_r_power == 6.0)
661 sigma_pow[i] = sigma6[i];
662 sigma_powm2[i] = sigma6[i]/sigma2[i];
664 else if (sc_r_power == 48.0)
666 sigma_pow[i] = sigma6[i]*sigma6[i]; /* sigma^12 */
667 sigma_pow[i] = sigma_pow[i]*sigma_pow[i]; /* sigma^24 */
668 sigma_pow[i] = sigma_pow[i]*sigma_pow[i]; /* sigma^48 */
669 sigma_powm2[i] = sigma_pow[i]/sigma2[i];
672 { /* not really supported as input, but in here for testing the general case*/
673 sigma_pow[i] = pow(sigma2[i],sc_r_power/2);
674 sigma_powm2[i] = sigma_pow[i]/(sigma2[i]);
678 /* only use softcore if one of the states has a zero endstate - softcore is for avoiding infinities!*/
679 if ((c12[0] > 0) && (c12[1] > 0)) {
683 alpha_vdw_eff = alpha_vdw;
684 alpha_coul_eff = alpha_coul;
687 /* Loop over A and B states again */
695 /* Only spend time on A or B state if it is non-zero */
696 if( (qq[i] != 0) || (c6[i] != 0) || (c12[i] != 0) )
699 rpinv = 1.0/(alpha_coul_eff*lfac_coul[i]*sigma_pow[i]+rp);
700 r_coul = pow(rpinv,-1.0/sc_r_power);
702 /* Electrostatics table lookup data */
703 rtab = r_coul*tabscale;
711 Geps = eps*vftab[ntab+2];
712 Heps2 = eps2*vftab[ntab+3];
715 FF = Fp+Geps+2.0*Heps2;
717 fscal_elec[i] = -qq[i]*FF*r_coul*rpinv*tabscale;
720 rpinv = 1.0/(alpha_vdw_eff*lfac_vdw[i]*sigma_pow[i]+rp);
721 r_vdw = pow(rpinv,-1.0/sc_r_power);
722 /* Vdw table lookup data */
723 rtab = r_vdw*tabscale;
731 Geps = eps*vftab[ntab+6];
732 Heps2 = eps2*vftab[ntab+7];
735 FF = Fp+Geps+2.0*Heps2;
737 fscal_vdw[i] = -c6[i]*FF;
742 Geps = eps*vftab[ntab+10];
743 Heps2 = eps2*vftab[ntab+11];
746 FF = Fp+Geps+2.0*Heps2;
747 vvdw[i] += c12[i]*VV;
748 fscal_vdw[i] -= c12[i]*FF;
749 fscal_vdw[i] *= r_vdw*rpinv*tabscale;
752 /* Now we have velec[i], vvdw[i], and fscal[i] for both states */
753 /* Assemble A and B states */
761 velecsum += LFC[i]*velec[i];
762 vvdwsum += LFV[i]*vvdw[i];
764 fscal += (LFC[i]*fscal_elec[i]+LFV[i]*fscal_vdw[i])*rpm2;
766 dvdl_coul += velec[i]*DLF[i] + LFC[i]*alpha_coul_eff*dlfac_coul[i]*fscal_elec[i]*sigma_pow[i];
767 dvdl_vdw += vvdw[i]*DLF[i] + LFV[i]*alpha_vdw_eff*dlfac_vdw[i]*fscal_vdw[i]*sigma_pow[i];
770 dvdl[efptCOUL] += dvdl_coul;
771 dvdl[efptVDW] += dvdl_vdw;
773 *velectot = velecsum;