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;
80 int n0, n1C, n1V, nnn;
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 */
302 sigma6[i] = sigma6_min;
303 sigma2[i] = sigma2_min;
308 sigma6[i] = sigma6_def;
309 sigma2[i] = sigma2_def;
311 if (sc_r_power == 6.0)
313 sigma_pow[i] = sigma6[i];
314 sigma_powm2[i] = sigma6[i]/sigma2[i];
316 else if (sc_r_power == 48.0)
318 sigma_pow[i] = sigma6[i]*sigma6[i]; /* sigma^12 */
319 sigma_pow[i] = sigma_pow[i]*sigma_pow[i]; /* sigma^24 */
320 sigma_pow[i] = sigma_pow[i]*sigma_pow[i]; /* sigma^48 */
321 sigma_powm2[i] = sigma_pow[i]/sigma2[i];
324 { /* not really supported as input, but in here for testing the general case*/
325 sigma_pow[i] = pow(sigma2[i], sc_r_power/2);
326 sigma_powm2[i] = sigma_pow[i]/(sigma2[i]);
330 /* only use softcore if one of the states has a zero endstate - softcore is for avoiding infinities!*/
331 if ((c12[STATE_A] > 0) && (c12[STATE_B] > 0))
338 alpha_vdw_eff = alpha_vdw;
339 alpha_coul_eff = alpha_coul;
342 for (i = 0; i < NSTATES; i++)
349 /* Only spend time on A or B state if it is non-zero */
350 if ( (qq[i] != 0) || (c6[i] != 0) || (c12[i] != 0) )
353 /* this section has to be inside the loop becaue of the dependence on sigma_pow */
354 rpinvC = 1.0/(alpha_coul_eff*lfac_coul[i]*sigma_pow[i]+rp);
355 rinvC = pow(rpinvC, 1.0/sc_r_power);
358 rpinvV = 1.0/(alpha_vdw_eff*lfac_vdw[i]*sigma_pow[i]+rp);
359 rinvV = pow(rpinvV, 1.0/sc_r_power);
362 factor_coul = (rC <= rcoulomb) ? 1.0 : 0.0;
363 factor_vdw = (rV <= rvdw) ? 1.0 : 0.0;
371 n1C = tab_elemsize*n0;
377 n1V = tab_elemsize*n0;
384 case GMX_NBKERNEL_ELEC_COULOMB:
385 case GMX_NBKERNEL_ELEC_EWALD:
386 /* simple cutoff (yes, ewald is done all on direct space for free energy) */
387 Vcoul[i] = qq[i]*rinvC;
388 FscalC[i] = Vcoul[i]*rpinvC;
391 case GMX_NBKERNEL_ELEC_REACTIONFIELD:
393 Vcoul[i] = qq[i]*(rinvC+krf*rC*rC-crf);
394 FscalC[i] = qq[i]*(rinvC*rpinvC-2.0*krf);
397 case GMX_NBKERNEL_ELEC_CUBICSPLINETABLE:
398 /* non-Ewald tabulated coulomb */
402 Geps = epsC*VFtab[nnn+2];
403 Heps2 = eps2C*VFtab[nnn+3];
406 FF = Fp+Geps+2.0*Heps2;
408 FscalC[i] = -qq[i]*tabscale*FF*rC*rpinvC;
417 if (fr->coulomb_modifier == eintmodPOTSWITCH)
420 d = (d > 0.0) ? d : 0.0;
422 sw = 1.0+d2*d*(swV3+d*(swV4+d*swV5));
423 dsw = d2*(swF2+d*(swF3+d*swF4));
426 FscalC[i] = FscalC[i]*sw + Vcoul[i]*dsw;
429 if (bExactElecCutoff)
431 FscalC[i] = (rC < rcoulomb) ? FscalC[i] : 0.0;
432 Vcoul[i] = (rC < rcoulomb) ? Vcoul[i] : 0.0;
436 if ((c6[i] != 0) || (c12[i] != 0))
440 case GMX_NBKERNEL_VDW_LENNARDJONES:
442 if (sc_r_power == 6.0)
448 rinv6 = pow(rinvV, 6.0);
451 Vvdw12 = c12[i]*rinv6*rinv6;
452 if (fr->vdw_modifier == eintmodPOTSHIFT)
454 Vvdw[i] = ( (Vvdw12-c12[i]*sh_invrc6*sh_invrc6)*(1.0/12.0)
455 -(Vvdw6-c6[i]*sh_invrc6)*(1.0/6.0));
459 Vvdw[i] = Vvdw12*(1.0/12.0)-Vvdw6*(1.0/6.0);
461 FscalV[i] = (Vvdw12-Vvdw6)*rpinvV;
464 case GMX_NBKERNEL_VDW_BUCKINGHAM:
465 gmx_fatal(FARGS, "Buckingham free energy not supported.");
468 case GMX_NBKERNEL_VDW_CUBICSPLINETABLE:
474 Geps = epsV*VFtab[nnn+2];
475 Heps2 = eps2V*VFtab[nnn+3];
478 FF = Fp+Geps+2.0*Heps2;
480 FscalV[i] -= c6[i]*tabscale*FF*rV*rpinvV;
485 Geps = epsV*VFtab[nnn+6];
486 Heps2 = eps2V*VFtab[nnn+7];
489 FF = Fp+Geps+2.0*Heps2;
490 Vvdw[i] += c12[i]*VV;
491 FscalV[i] -= c12[i]*tabscale*FF*rV*rpinvV;
500 if (fr->vdw_modifier == eintmodPOTSWITCH)
503 d = (d > 0.0) ? d : 0.0;
505 sw = 1.0+d2*d*(swV3+d*(swV4+d*swV5));
506 dsw = d2*(swF2+d*(swF3+d*swF4));
509 FscalV[i] = FscalV[i]*sw + Vvdw[i]*dsw;
511 FscalV[i] = (rV < rvdw) ? FscalV[i] : 0.0;
512 Vvdw[i] = (rV < rvdw) ? Vvdw[i] : 0.0;
520 if (icoul == GMX_NBKERNEL_ELEC_EWALD)
522 /* because we compute the softcore normally,
523 we have to remove the ewald short range portion. Done outside of
524 the states loop because this part doesn't depend on the scaled R */
528 VV = gmx_erf(ewc*r)*rinv;
529 FF = rinv*rinv*(VV - ewc*M_2_SQRTPI*exp(-ewc*ewc*rsq));
537 for (i = 0; i < NSTATES; i++)
539 vctot -= LFC[i]*qq[i]*VV;
540 Fscal -= LFC[i]*qq[i]*FF;
541 dvdl_coul -= (DLF[i]*qq[i])*VV;
545 /* Assemble A and B states */
546 for (i = 0; i < NSTATES; i++)
548 vctot += LFC[i]*Vcoul[i];
549 vvtot += LFV[i]*Vvdw[i];
551 Fscal += LFC[i]*FscalC[i]*rpm2;
552 Fscal += LFV[i]*FscalV[i]*rpm2;
554 dvdl_coul += Vcoul[i]*DLF[i] + LFC[i]*alpha_coul_eff*dlfac_coul[i]*FscalC[i]*sigma_pow[i];
555 dvdl_vdw += Vvdw[i]*DLF[i] + LFV[i]*alpha_vdw_eff*dlfac_vdw[i]*FscalV[i]*sigma_pow[i];
567 f[j3+1] = f[j3+1] - ty;
568 f[j3+2] = f[j3+2] - tz;
574 f[ii3] = f[ii3] + fix;
575 f[ii3+1] = f[ii3+1] + fiy;
576 f[ii3+2] = f[ii3+2] + fiz;
577 fshift[is3] = fshift[is3] + fix;
578 fshift[is3+1] = fshift[is3+1] + fiy;
579 fshift[is3+2] = fshift[is3+2] + fiz;
582 Vc[ggid] = Vc[ggid] + vctot;
583 Vv[ggid] = Vv[ggid] + vvtot;
586 dvdl[efptCOUL] += dvdl_coul;
587 dvdl[efptVDW] += dvdl_vdw;
589 /* Estimate flops, average for free energy stuff:
590 * 12 flops per outer iteration
591 * 150 flops per inner iteration
593 inc_nrnb(nrnb, eNR_NBKERNEL_FREE_ENERGY, nlist->nri*12 + nlist->jindex[n]*150);
597 nb_free_energy_evaluate_single(real r2, real sc_r_power, real alpha_coul, real alpha_vdw,
598 real tabscale, real *vftab,
599 real qqA, real c6A, real c12A, real qqB, real c6B, real c12B,
600 real LFC[2], real LFV[2], real DLF[2],
601 real lfac_coul[2], real lfac_vdw[2], real dlfac_coul[2], real dlfac_vdw[2],
602 real sigma6_def, real sigma6_min, real sigma2_def, real sigma2_min,
603 real *velectot, real *vvdwtot, real *dvdl)
605 real r, rp, rpm2, rtab, eps, eps2, Y, F, Geps, Heps2, Fp, VV, FF, fscal;
606 real qq[2], c6[2], c12[2], sigma6[2], sigma2[2], sigma_pow[2], sigma_powm2[2];
607 real alpha_coul_eff, alpha_vdw_eff, dvdl_coul, dvdl_vdw;
608 real rpinv, r_coul, r_vdw, velecsum, vvdwsum;
609 real fscal_vdw[2], fscal_elec[2];
610 real velec[2], vvdw[2];
620 if (sc_r_power == 6.0)
622 rpm2 = r2*r2; /* r4 */
623 rp = rpm2*r2; /* r6 */
625 else if (sc_r_power == 48.0)
627 rp = r2*r2*r2; /* r6 */
628 rp = rp*rp; /* r12 */
629 rp = rp*rp; /* r24 */
630 rp = rp*rp; /* r48 */
631 rpm2 = rp/r2; /* r46 */
635 rp = pow(r2, 0.5*sc_r_power); /* not currently supported as input, but can handle it */
639 /* Loop over state A(0) and B(1) */
640 for (i = 0; i < 2; i++)
642 if ((c6[i] > 0) && (c12[i] > 0))
644 /* The c6 & c12 coefficients now contain the constants 6.0 and 12.0, respectively.
645 * Correct for this by multiplying with (1/12.0)/(1/6.0)=6.0/12.0=0.5.
647 sigma6[i] = 0.5*c12[i]/c6[i];
648 sigma2[i] = pow(0.5*c12[i]/c6[i], 1.0/3.0);
649 /* should be able to get rid of this ^^^ internal pow call eventually. Will require agreement on
650 what data to store externally. Can't be fixed without larger scale changes, so not 4.6 */
651 if (sigma6[i] < sigma6_min) /* for disappearing coul and vdw with soft core at the same time */
653 sigma6[i] = sigma6_min;
654 sigma2[i] = sigma2_min;
659 sigma6[i] = sigma6_def;
660 sigma2[i] = sigma2_def;
662 if (sc_r_power == 6.0)
664 sigma_pow[i] = sigma6[i];
665 sigma_powm2[i] = sigma6[i]/sigma2[i];
667 else if (sc_r_power == 48.0)
669 sigma_pow[i] = sigma6[i]*sigma6[i]; /* sigma^12 */
670 sigma_pow[i] = sigma_pow[i]*sigma_pow[i]; /* sigma^24 */
671 sigma_pow[i] = sigma_pow[i]*sigma_pow[i]; /* sigma^48 */
672 sigma_powm2[i] = sigma_pow[i]/sigma2[i];
675 { /* not really supported as input, but in here for testing the general case*/
676 sigma_pow[i] = pow(sigma2[i], sc_r_power/2);
677 sigma_powm2[i] = sigma_pow[i]/(sigma2[i]);
681 /* only use softcore if one of the states has a zero endstate - softcore is for avoiding infinities!*/
682 if ((c12[0] > 0) && (c12[1] > 0))
689 alpha_vdw_eff = alpha_vdw;
690 alpha_coul_eff = alpha_coul;
693 /* Loop over A and B states again */
694 for (i = 0; i < 2; i++)
701 /* Only spend time on A or B state if it is non-zero */
702 if ( (qq[i] != 0) || (c6[i] != 0) || (c12[i] != 0) )
705 rpinv = 1.0/(alpha_coul_eff*lfac_coul[i]*sigma_pow[i]+rp);
706 r_coul = pow(rpinv, -1.0/sc_r_power);
708 /* Electrostatics table lookup data */
709 rtab = r_coul*tabscale;
717 Geps = eps*vftab[ntab+2];
718 Heps2 = eps2*vftab[ntab+3];
721 FF = Fp+Geps+2.0*Heps2;
723 fscal_elec[i] = -qq[i]*FF*r_coul*rpinv*tabscale;
726 rpinv = 1.0/(alpha_vdw_eff*lfac_vdw[i]*sigma_pow[i]+rp);
727 r_vdw = pow(rpinv, -1.0/sc_r_power);
728 /* Vdw table lookup data */
729 rtab = r_vdw*tabscale;
737 Geps = eps*vftab[ntab+6];
738 Heps2 = eps2*vftab[ntab+7];
741 FF = Fp+Geps+2.0*Heps2;
743 fscal_vdw[i] = -c6[i]*FF;
748 Geps = eps*vftab[ntab+10];
749 Heps2 = eps2*vftab[ntab+11];
752 FF = Fp+Geps+2.0*Heps2;
753 vvdw[i] += c12[i]*VV;
754 fscal_vdw[i] -= c12[i]*FF;
755 fscal_vdw[i] *= r_vdw*rpinv*tabscale;
758 /* Now we have velec[i], vvdw[i], and fscal[i] for both states */
759 /* Assemble A and B states */
765 for (i = 0; i < 2; i++)
767 velecsum += LFC[i]*velec[i];
768 vvdwsum += LFV[i]*vvdw[i];
770 fscal += (LFC[i]*fscal_elec[i]+LFV[i]*fscal_vdw[i])*rpm2;
772 dvdl_coul += velec[i]*DLF[i] + LFC[i]*alpha_coul_eff*dlfac_coul[i]*fscal_elec[i]*sigma_pow[i];
773 dvdl_vdw += vvdw[i]*DLF[i] + LFV[i]*alpha_vdw_eff*dlfac_vdw[i]*fscal_vdw[i]*sigma_pow[i];
776 dvdl[efptCOUL] += dvdl_coul;
777 dvdl[efptVDW] += dvdl_vdw;
779 *velectot = velecsum;