1 /* -*- mode: c; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; c-file-style: "stroustrup"; -*-
4 * This source code is part of
8 * GROningen MAchine for Chemical Simulations
11 * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
12 * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
13 * Copyright (c) 2001-2004, The GROMACS development team,
14 * check out http://www.gromacs.org for more information.
16 * This program is free software; you can redistribute it and/or
17 * modify it under the terms of the GNU General Public License
18 * as published by the Free Software Foundation; either version 2
19 * of the License, or (at your option) any later version.
21 * If you want to redistribute modifications, please consider that
22 * scientific software is very special. Version control is crucial -
23 * bugs must be traceable. We will be happy to consider code for
24 * inclusion in the official distribution, but derived work must not
25 * be called official GROMACS. Details are found in the README & COPYING
26 * files - if they are missing, get the official version at www.gromacs.org.
28 * To help us fund GROMACS development, we humbly ask that you cite
29 * the papers on the package - you can find them in the top README file.
31 * For more info, check our website at http://www.gromacs.org
34 * GROningen Mixture of Alchemy and Childrens' Stories
44 #include "nonbonded.h"
45 #include "nb_kernel.h"
49 gmx_nb_free_energy_kernel(t_nblist * nlist,
54 nb_kernel_data_t * kernel_data,
61 int i,j,n,ii,is3,ii3,k,nj0,nj1,jnr,j3,ggid;
63 real Fscal,FscalC[NSTATES],FscalV[NSTATES],tx,ty,tz;
64 real Vcoul[NSTATES],Vvdw[NSTATES];
65 real rinv6,r,rt,rtC,rtV;
67 real qq[NSTATES],vctot,krsq;
68 int ntiA,ntiB,tj[NSTATES];
69 real Vvdw6, Vvdw12,vvtot;
70 real ix,iy,iz,fix,fiy,fiz;
71 real dx,dy,dz,rsq,rinv;
72 real c6[NSTATES],c12[NSTATES];
73 real LFC[NSTATES],LFV[NSTATES],DLF[NSTATES];
74 double dvdl_coul,dvdl_vdw;
75 real lfac_coul[NSTATES],dlfac_coul[NSTATES],lfac_vdw[NSTATES],dlfac_vdw[NSTATES];
76 real sigma6[NSTATES],alpha_vdw_eff,alpha_coul_eff,sigma2_def,sigma2_min;
77 real rp,rpm2,rC,rV,rinvC,rpinvC,rinvV,rpinvV;
78 real sigma2[NSTATES],sigma_pow[NSTATES],sigma_powm2[NSTATES],rs,rs2;
79 int do_coultab,do_vdwtab,do_tab,tab_elemsize;
81 real Y,F,G,H,Fp,Geps,Heps2,epsC,eps2C,epsV,eps2V,VV,FF;
102 real sigma6_min,sigma6_def,lam_power,sc_power,sc_r_power;
103 real alpha_coul,alpha_vdw,lambda_coul,lambda_vdw,ewc;
109 real rcoulomb,rvdw,factor_coul,factor_vdw,sh_invrc6;
110 gmx_bool bExactElecCutoff,bExactVdwCutoff;
111 real rcutoff,rcutoff2,rswitch,d,d2,swV3,swV4,swV5,swF2,swF3,swF4,sw,dsw,rinvcorr;
116 fshift = fr->fshift[0];
117 Vc = kernel_data->energygrp_elec;
118 Vv = kernel_data->energygrp_vdw;
119 tabscale = kernel_data->table_elec_vdw->scale;
120 VFtab = kernel_data->table_elec_vdw->data;
124 jindex = nlist->jindex;
126 icoul = nlist->ielec;
128 shift = nlist->shift;
131 shiftvec = fr->shift_vec[0];
132 chargeA = mdatoms->chargeA;
133 chargeB = mdatoms->chargeB;
137 ewc = fr->ewaldcoeff;
138 Vc = kernel_data->energygrp_elec;
139 typeA = mdatoms->typeA;
140 typeB = mdatoms->typeB;
143 Vv = kernel_data->energygrp_vdw;
144 tabscale = kernel_data->table_elec_vdw->scale;
145 VFtab = kernel_data->table_elec_vdw->data;
146 lambda_coul = kernel_data->lambda[efptCOUL];
147 lambda_vdw = kernel_data->lambda[efptVDW];
148 dvdl = kernel_data->dvdl;
149 alpha_coul = fr->sc_alphacoul;
150 alpha_vdw = fr->sc_alphavdw;
151 lam_power = fr->sc_power;
152 sc_r_power = fr->sc_r_power;
153 sigma6_def = fr->sc_sigma6_def;
154 sigma6_min = fr->sc_sigma6_min;
155 bDoForces = kernel_data->flags & GMX_NONBONDED_DO_FORCE;
157 rcoulomb = fr->rcoulomb;
159 sh_invrc6 = fr->ic->sh_invrc6;
161 if(fr->coulomb_modifier==eintmodPOTSWITCH || fr->vdw_modifier==eintmodPOTSWITCH)
163 rcutoff = (fr->coulomb_modifier==eintmodPOTSWITCH) ? fr->rcoulomb : fr->rvdw;
164 rcutoff2 = rcutoff*rcutoff;
165 rswitch = (fr->coulomb_modifier==eintmodPOTSWITCH) ? fr->rcoulomb_switch : fr->rvdw_switch;
167 swV3 = -10.0/(d*d*d);
168 swV4 = 15.0/(d*d*d*d);
169 swV5 = -6.0/(d*d*d*d*d);
170 swF2 = -30.0/(d*d*d);
171 swF3 = 60.0/(d*d*d*d);
172 swF4 = -30.0/(d*d*d*d*d);
176 /* Stupid compilers dont realize these variables will not be used */
186 bExactElecCutoff = (fr->coulomb_modifier!=eintmodNONE) || fr->eeltype == eelRF_ZERO;
187 bExactVdwCutoff = (fr->vdw_modifier!=eintmodNONE);
189 /* fix compiler warnings */
198 /* Lambda factor for state A, 1-lambda*/
199 LFC[STATE_A] = 1.0 - lambda_coul;
200 LFV[STATE_A] = 1.0 - lambda_vdw;
202 /* Lambda factor for state B, lambda*/
203 LFC[STATE_B] = lambda_coul;
204 LFV[STATE_B] = lambda_vdw;
206 /*derivative of the lambda factor for state A and B */
210 for (i=0;i<NSTATES;i++)
212 lfac_coul[i] = (lam_power==2 ? (1-LFC[i])*(1-LFC[i]) : (1-LFC[i]));
213 dlfac_coul[i] = DLF[i]*lam_power/sc_r_power*(lam_power==2 ? (1-LFC[i]) : 1);
214 lfac_vdw[i] = (lam_power==2 ? (1-LFV[i])*(1-LFV[i]) : (1-LFV[i]));
215 dlfac_vdw[i] = DLF[i]*lam_power/sc_r_power*(lam_power==2 ? (1-LFV[i]) : 1);
218 sigma2_def = pow(sigma6_def,1.0/3.0);
219 sigma2_min = pow(sigma6_min,1.0/3.0);
221 /* Ewald (not PME) table is special (icoul==enbcoulFEWALD) */
223 do_coultab = (icoul==GMX_NBKERNEL_ELEC_CUBICSPLINETABLE);
224 do_vdwtab = (ivdw==GMX_NBKERNEL_VDW_CUBICSPLINETABLE);
226 do_tab = do_coultab || do_vdwtab;
228 /* we always use the combined table here */
231 for(n=0; (n<nri); n++)
235 shY = shiftvec[is3+1];
236 shZ = shiftvec[is3+2];
244 iqA = facel*chargeA[ii];
245 iqB = facel*chargeB[ii];
246 ntiA = 2*ntype*typeA[ii];
247 ntiB = 2*ntype*typeB[ii];
254 for(k=nj0; (k<nj1); k++)
261 rsq = dx*dx+dy*dy+dz*dz;
262 rinv = gmx_invsqrt(rsq);
264 if (sc_r_power == 6.0)
266 rpm2 = rsq*rsq; /* r4 */
267 rp = rpm2*rsq; /* r6 */
269 else if (sc_r_power == 48.0)
271 rp = rsq*rsq*rsq; /* r6 */
272 rp = rp*rp; /* r12 */
273 rp = rp*rp; /* r24 */
274 rp = rp*rp; /* r48 */
275 rpm2 = rp/rsq; /* r46 */
279 rp = pow(r,sc_r_power); /* not currently supported as input, but can handle it */
283 tj[STATE_A] = ntiA+2*typeA[jnr];
284 tj[STATE_B] = ntiB+2*typeB[jnr];
285 qq[STATE_A] = iqA*chargeA[jnr];
286 qq[STATE_B] = iqB*chargeB[jnr];
288 for (i=0;i<NSTATES;i++)
292 c12[i] = nbfp[tj[i]+1];
293 if((c6[i] > 0) && (c12[i] > 0))
295 /* c12 is stored scaled with 12.0 and c6 is scaled with 6.0 - correct for this */
296 sigma6[i] = 0.5*c12[i]/c6[i];
297 sigma2[i] = pow(sigma6[i],1.0/3.0);
298 /* should be able to get rid of this ^^^ internal pow call eventually. Will require agreement on
299 what data to store externally. Can't be fixed without larger scale changes, so not 4.6 */
300 if (sigma6[i] < sigma6_min) { /* for disappearing coul and vdw with soft core at the same time */
301 sigma6[i] = sigma6_min;
302 sigma2[i] = sigma2_min;
307 sigma6[i] = sigma6_def;
308 sigma2[i] = sigma2_def;
310 if (sc_r_power == 6.0)
312 sigma_pow[i] = sigma6[i];
313 sigma_powm2[i] = sigma6[i]/sigma2[i];
315 else if (sc_r_power == 48.0)
317 sigma_pow[i] = sigma6[i]*sigma6[i]; /* sigma^12 */
318 sigma_pow[i] = sigma_pow[i]*sigma_pow[i]; /* sigma^24 */
319 sigma_pow[i] = sigma_pow[i]*sigma_pow[i]; /* sigma^48 */
320 sigma_powm2[i] = sigma_pow[i]/sigma2[i];
323 { /* not really supported as input, but in here for testing the general case*/
324 sigma_pow[i] = pow(sigma2[i],sc_r_power/2);
325 sigma_powm2[i] = sigma_pow[i]/(sigma2[i]);
329 /* only use softcore if one of the states has a zero endstate - softcore is for avoiding infinities!*/
330 if ((c12[STATE_A] > 0) && (c12[STATE_B] > 0)) {
334 alpha_vdw_eff = alpha_vdw;
335 alpha_coul_eff = alpha_coul;
338 for (i=0;i<NSTATES;i++)
345 /* Only spend time on A or B state if it is non-zero */
346 if( (qq[i] != 0) || (c6[i] != 0) || (c12[i] != 0) )
349 /* this section has to be inside the loop becaue of the dependence on sigma_pow */
350 rpinvC = 1.0/(alpha_coul_eff*lfac_coul[i]*sigma_pow[i]+rp);
351 rinvC = pow(rpinvC,1.0/sc_r_power);
354 rpinvV = 1.0/(alpha_vdw_eff*lfac_vdw[i]*sigma_pow[i]+rp);
355 rinvV = pow(rpinvV,1.0/sc_r_power);
358 factor_coul = (rC<=rcoulomb) ? 1.0 : 0.0;
359 factor_vdw = (rV<=rvdw) ? 1.0 : 0.0;
367 n1C = tab_elemsize*n0;
373 n1V = tab_elemsize*n0;
380 case GMX_NBKERNEL_ELEC_COULOMB:
381 case GMX_NBKERNEL_ELEC_EWALD:
382 /* simple cutoff (yes, ewald is done all on direct space for free energy) */
383 Vcoul[i] = qq[i]*rinvC;
384 FscalC[i] = Vcoul[i]*rpinvC;
387 case GMX_NBKERNEL_ELEC_REACTIONFIELD:
389 Vcoul[i] = qq[i]*(rinvC+krf*rC*rC-crf);
390 FscalC[i] = qq[i]*(rinvC*rpinvC-2.0*krf);
393 case GMX_NBKERNEL_ELEC_CUBICSPLINETABLE:
394 /* non-Ewald tabulated coulomb */
398 Geps = epsC*VFtab[nnn+2];
399 Heps2 = eps2C*VFtab[nnn+3];
402 FF = Fp+Geps+2.0*Heps2;
404 FscalC[i] = -qq[i]*tabscale*FF*rC*rpinvC;
413 if(fr->coulomb_modifier==eintmodPOTSWITCH)
416 d = (d>0.0) ? d : 0.0;
418 sw = 1.0+d2*d*(swV3+d*(swV4+d*swV5));
419 dsw = d2*(swF2+d*(swF3+d*swF4));
422 FscalC[i] = FscalC[i]*sw + Vcoul[i]*dsw;
427 FscalC[i] = (rC<rcoulomb) ? FscalC[i] : 0.0;
428 Vcoul[i] = (rC<rcoulomb) ? Vcoul[i] : 0.0;
432 if((c6[i] != 0) || (c12[i] != 0))
436 case GMX_NBKERNEL_VDW_LENNARDJONES:
438 if (sc_r_power == 6.0)
444 rinv6 = pow(rinvV,6.0);
447 Vvdw12 = c12[i]*rinv6*rinv6;
448 if(fr->vdw_modifier==eintmodPOTSHIFT)
450 Vvdw[i] = ( (Vvdw12-c12[i]*sh_invrc6*sh_invrc6)*(1.0/12.0)
451 -(Vvdw6-c6[i]*sh_invrc6)*(1.0/6.0));
455 Vvdw[i] = Vvdw12*(1.0/12.0)-Vvdw6*(1.0/6.0);
457 FscalV[i] = (Vvdw12-Vvdw6)*rpinvV;
460 case GMX_NBKERNEL_VDW_BUCKINGHAM:
461 gmx_fatal(FARGS,"Buckingham free energy not supported.");
464 case GMX_NBKERNEL_VDW_CUBICSPLINETABLE:
470 Geps = epsV*VFtab[nnn+2];
471 Heps2 = eps2V*VFtab[nnn+3];
474 FF = Fp+Geps+2.0*Heps2;
476 FscalV[i] -= c6[i]*tabscale*FF*rV*rpinvV;
481 Geps = epsV*VFtab[nnn+6];
482 Heps2 = eps2V*VFtab[nnn+7];
485 FF = Fp+Geps+2.0*Heps2;
486 Vvdw[i] += c12[i]*VV;
487 FscalV[i] -= c12[i]*tabscale*FF*rV*rpinvV;
496 if(fr->vdw_modifier==eintmodPOTSWITCH)
499 d = (d>0.0) ? d : 0.0;
501 sw = 1.0+d2*d*(swV3+d*(swV4+d*swV5));
502 dsw = d2*(swF2+d*(swF3+d*swF4));
505 FscalV[i] = FscalV[i]*sw + Vvdw[i]*dsw;
507 FscalV[i] = (rV<rvdw) ? FscalV[i] : 0.0;
508 Vvdw[i] = (rV<rvdw) ? Vvdw[i] : 0.0;
516 if (icoul==GMX_NBKERNEL_ELEC_EWALD)
518 /* because we compute the softcore normally,
519 we have to remove the ewald short range portion. Done outside of
520 the states loop because this part doesn't depend on the scaled R */
524 VV = gmx_erf(ewc*r)*rinv;
525 FF = rinv*rinv*(VV - ewc*M_2_SQRTPI*exp(-ewc*ewc*rsq));
533 for (i=0;i<NSTATES;i++)
535 vctot -= LFC[i]*qq[i]*VV;
536 Fscal -= LFC[i]*qq[i]*FF;
537 dvdl_coul -= (DLF[i]*qq[i])*VV;
541 /* Assemble A and B states */
542 for (i=0;i<NSTATES;i++)
544 vctot += LFC[i]*Vcoul[i];
545 vvtot += LFV[i]*Vvdw[i];
547 Fscal += LFC[i]*FscalC[i]*rpm2;
548 Fscal += LFV[i]*FscalV[i]*rpm2;
550 dvdl_coul += Vcoul[i]*DLF[i] + LFC[i]*alpha_coul_eff*dlfac_coul[i]*FscalC[i]*sigma_pow[i];
551 dvdl_vdw += Vvdw[i]*DLF[i] + LFV[i]*alpha_vdw_eff*dlfac_vdw[i]*FscalV[i]*sigma_pow[i];
563 f[j3+1] = f[j3+1] - ty;
564 f[j3+2] = f[j3+2] - tz;
570 f[ii3] = f[ii3] + fix;
571 f[ii3+1] = f[ii3+1] + fiy;
572 f[ii3+2] = f[ii3+2] + fiz;
573 fshift[is3] = fshift[is3] + fix;
574 fshift[is3+1] = fshift[is3+1] + fiy;
575 fshift[is3+2] = fshift[is3+2] + fiz;
578 Vc[ggid] = Vc[ggid] + vctot;
579 Vv[ggid] = Vv[ggid] + vvtot;
582 dvdl[efptCOUL] += dvdl_coul;
583 dvdl[efptVDW] += dvdl_vdw;
585 /* Estimate flops, average for free energy stuff:
586 * 12 flops per outer iteration
587 * 150 flops per inner iteration
589 inc_nrnb(nrnb,eNR_NBKERNEL_FREE_ENERGY,nlist->nri*12 + nlist->jindex[n]*150);
593 nb_free_energy_evaluate_single(real r2,real sc_r_power,real alpha_coul,real alpha_vdw,
594 real tabscale,real *vftab,
595 real qqA, real c6A, real c12A, real qqB, real c6B, real c12B,
596 real LFC[2], real LFV[2],real DLF[2],
597 real lfac_coul[2], real lfac_vdw[2],real dlfac_coul[2], real dlfac_vdw[2],
598 real sigma6_def, real sigma6_min,real sigma2_def, real sigma2_min,
599 real *velectot, real *vvdwtot, real *dvdl)
601 real r,rp,rpm2,rtab,eps,eps2,Y,F,Geps,Heps2,Fp,VV,FF,fscal;
602 real qq[2],c6[2],c12[2],sigma6[2],sigma2[2],sigma_pow[2],sigma_powm2[2];
603 real alpha_coul_eff,alpha_vdw_eff,dvdl_coul,dvdl_vdw;
604 real rpinv,r_coul,r_vdw,velecsum,vvdwsum;
605 real fscal_vdw[2],fscal_elec[2];
606 real velec[2],vvdw[2];
616 if (sc_r_power == 6.0)
618 rpm2 = r2*r2; /* r4 */
619 rp = rpm2*r2; /* r6 */
621 else if (sc_r_power == 48.0)
623 rp = r2*r2*r2; /* r6 */
624 rp = rp*rp; /* r12 */
625 rp = rp*rp; /* r24 */
626 rp = rp*rp; /* r48 */
627 rpm2 = rp/r2; /* r46 */
631 rp = pow(r2,0.5*sc_r_power); /* not currently supported as input, but can handle it */
635 /* Loop over state A(0) and B(1) */
638 if((c6[i] > 0) && (c12[i] > 0))
640 /* The c6 & c12 coefficients now contain the constants 6.0 and 12.0, respectively.
641 * Correct for this by multiplying with (1/12.0)/(1/6.0)=6.0/12.0=0.5.
643 sigma6[i] = 0.5*c12[i]/c6[i];
644 sigma2[i] = pow(0.5*c12[i]/c6[i],1.0/3.0);
645 /* should be able to get rid of this ^^^ internal pow call eventually. Will require agreement on
646 what data to store externally. Can't be fixed without larger scale changes, so not 4.6 */
647 if (sigma6[i] < sigma6_min) { /* for disappearing coul and vdw with soft core at the same time */
648 sigma6[i] = sigma6_min;
649 sigma2[i] = sigma2_min;
654 sigma6[i] = sigma6_def;
655 sigma2[i] = sigma2_def;
657 if (sc_r_power == 6.0)
659 sigma_pow[i] = sigma6[i];
660 sigma_powm2[i] = sigma6[i]/sigma2[i];
662 else if (sc_r_power == 48.0)
664 sigma_pow[i] = sigma6[i]*sigma6[i]; /* sigma^12 */
665 sigma_pow[i] = sigma_pow[i]*sigma_pow[i]; /* sigma^24 */
666 sigma_pow[i] = sigma_pow[i]*sigma_pow[i]; /* sigma^48 */
667 sigma_powm2[i] = sigma_pow[i]/sigma2[i];
670 { /* not really supported as input, but in here for testing the general case*/
671 sigma_pow[i] = pow(sigma2[i],sc_r_power/2);
672 sigma_powm2[i] = sigma_pow[i]/(sigma2[i]);
676 /* only use softcore if one of the states has a zero endstate - softcore is for avoiding infinities!*/
677 if ((c12[0] > 0) && (c12[1] > 0)) {
681 alpha_vdw_eff = alpha_vdw;
682 alpha_coul_eff = alpha_coul;
685 /* Loop over A and B states again */
693 /* Only spend time on A or B state if it is non-zero */
694 if( (qq[i] != 0) || (c6[i] != 0) || (c12[i] != 0) )
697 rpinv = 1.0/(alpha_coul_eff*lfac_coul[i]*sigma_pow[i]+rp);
698 r_coul = pow(rpinv,-1.0/sc_r_power);
700 /* Electrostatics table lookup data */
701 rtab = r_coul*tabscale;
709 Geps = eps*vftab[ntab+2];
710 Heps2 = eps2*vftab[ntab+3];
713 FF = Fp+Geps+2.0*Heps2;
715 fscal_elec[i] = -qq[i]*FF*r_coul*rpinv*tabscale;
718 rpinv = 1.0/(alpha_vdw_eff*lfac_vdw[i]*sigma_pow[i]+rp);
719 r_vdw = pow(rpinv,-1.0/sc_r_power);
720 /* Vdw table lookup data */
721 rtab = r_vdw*tabscale;
729 Geps = eps*vftab[ntab+6];
730 Heps2 = eps2*vftab[ntab+7];
733 FF = Fp+Geps+2.0*Heps2;
735 fscal_vdw[i] = -c6[i]*FF;
740 Geps = eps*vftab[ntab+10];
741 Heps2 = eps2*vftab[ntab+11];
744 FF = Fp+Geps+2.0*Heps2;
745 vvdw[i] += c12[i]*VV;
746 fscal_vdw[i] -= c12[i]*FF;
747 fscal_vdw[i] *= r_vdw*rpinv*tabscale;
750 /* Now we have velec[i], vvdw[i], and fscal[i] for both states */
751 /* Assemble A and B states */
759 velecsum += LFC[i]*velec[i];
760 vvdwsum += LFV[i]*vvdw[i];
762 fscal += (LFC[i]*fscal_elec[i]+LFV[i]*fscal_vdw[i])*rpm2;
764 dvdl_coul += velec[i]*DLF[i] + LFC[i]*alpha_coul_eff*dlfac_coul[i]*fscal_elec[i]*sigma_pow[i];
765 dvdl_vdw += vvdw[i]*DLF[i] + LFV[i]*alpha_vdw_eff*dlfac_vdw[i]*fscal_vdw[i]*sigma_pow[i];
768 dvdl[efptCOUL] += dvdl_coul;
769 dvdl[efptVDW] += dvdl_vdw;
771 *velectot = velecsum;