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, 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 typeA = mdatoms->typeA;
139 typeB = mdatoms->typeB;
142 lambda_coul = kernel_data->lambda[efptCOUL];
143 lambda_vdw = kernel_data->lambda[efptVDW];
144 dvdl = kernel_data->dvdl;
145 alpha_coul = fr->sc_alphacoul;
146 alpha_vdw = fr->sc_alphavdw;
147 lam_power = fr->sc_power;
148 sc_r_power = fr->sc_r_power;
149 sigma6_def = fr->sc_sigma6_def;
150 sigma6_min = fr->sc_sigma6_min;
151 bDoForces = kernel_data->flags & GMX_NONBONDED_DO_FORCE;
153 rcoulomb = fr->rcoulomb;
155 sh_invrc6 = fr->ic->sh_invrc6;
157 if (fr->coulomb_modifier == eintmodPOTSWITCH || fr->vdw_modifier == eintmodPOTSWITCH)
159 rcutoff = (fr->coulomb_modifier == eintmodPOTSWITCH) ? fr->rcoulomb : fr->rvdw;
160 rcutoff2 = rcutoff*rcutoff;
161 rswitch = (fr->coulomb_modifier == eintmodPOTSWITCH) ? fr->rcoulomb_switch : fr->rvdw_switch;
163 swV3 = -10.0/(d*d*d);
164 swV4 = 15.0/(d*d*d*d);
165 swV5 = -6.0/(d*d*d*d*d);
166 swF2 = -30.0/(d*d*d);
167 swF3 = 60.0/(d*d*d*d);
168 swF4 = -30.0/(d*d*d*d*d);
172 /* Stupid compilers dont realize these variables will not be used */
182 bExactElecCutoff = (fr->coulomb_modifier != eintmodNONE) || fr->eeltype == eelRF_ZERO;
183 bExactVdwCutoff = (fr->vdw_modifier != eintmodNONE);
185 /* fix compiler warnings */
194 /* Lambda factor for state A, 1-lambda*/
195 LFC[STATE_A] = 1.0 - lambda_coul;
196 LFV[STATE_A] = 1.0 - lambda_vdw;
198 /* Lambda factor for state B, lambda*/
199 LFC[STATE_B] = lambda_coul;
200 LFV[STATE_B] = lambda_vdw;
202 /*derivative of the lambda factor for state A and B */
206 for (i = 0; i < NSTATES; i++)
208 lfac_coul[i] = (lam_power == 2 ? (1-LFC[i])*(1-LFC[i]) : (1-LFC[i]));
209 dlfac_coul[i] = DLF[i]*lam_power/sc_r_power*(lam_power == 2 ? (1-LFC[i]) : 1);
210 lfac_vdw[i] = (lam_power == 2 ? (1-LFV[i])*(1-LFV[i]) : (1-LFV[i]));
211 dlfac_vdw[i] = DLF[i]*lam_power/sc_r_power*(lam_power == 2 ? (1-LFV[i]) : 1);
214 sigma2_def = pow(sigma6_def, 1.0/3.0);
215 sigma2_min = pow(sigma6_min, 1.0/3.0);
217 /* Ewald (not PME) table is special (icoul==enbcoulFEWALD) */
219 do_coultab = (icoul == GMX_NBKERNEL_ELEC_CUBICSPLINETABLE);
220 do_vdwtab = (ivdw == GMX_NBKERNEL_VDW_CUBICSPLINETABLE);
222 do_tab = do_coultab || do_vdwtab;
224 /* we always use the combined table here */
227 for (n = 0; (n < nri); n++)
231 shY = shiftvec[is3+1];
232 shZ = shiftvec[is3+2];
240 iqA = facel*chargeA[ii];
241 iqB = facel*chargeB[ii];
242 ntiA = 2*ntype*typeA[ii];
243 ntiB = 2*ntype*typeB[ii];
250 for (k = nj0; (k < nj1); k++)
257 rsq = dx*dx+dy*dy+dz*dz;
258 rinv = gmx_invsqrt(rsq);
260 if (sc_r_power == 6.0)
262 rpm2 = rsq*rsq; /* r4 */
263 rp = rpm2*rsq; /* r6 */
265 else if (sc_r_power == 48.0)
267 rp = rsq*rsq*rsq; /* r6 */
268 rp = rp*rp; /* r12 */
269 rp = rp*rp; /* r24 */
270 rp = rp*rp; /* r48 */
271 rpm2 = rp/rsq; /* r46 */
275 rp = pow(r, sc_r_power); /* not currently supported as input, but can handle it */
279 tj[STATE_A] = ntiA+2*typeA[jnr];
280 tj[STATE_B] = ntiB+2*typeB[jnr];
281 qq[STATE_A] = iqA*chargeA[jnr];
282 qq[STATE_B] = iqB*chargeB[jnr];
284 for (i = 0; i < NSTATES; i++)
288 c12[i] = nbfp[tj[i]+1];
289 if ((c6[i] > 0) && (c12[i] > 0))
291 /* c12 is stored scaled with 12.0 and c6 is scaled with 6.0 - correct for this */
292 sigma6[i] = 0.5*c12[i]/c6[i];
293 sigma2[i] = pow(sigma6[i], 1.0/3.0);
294 /* should be able to get rid of this ^^^ internal pow call eventually. Will require agreement on
295 what data to store externally. Can't be fixed without larger scale changes, so not 4.6 */
296 if (sigma6[i] < sigma6_min) /* for disappearing coul and vdw with soft core at the same time */
298 sigma6[i] = sigma6_min;
299 sigma2[i] = sigma2_min;
304 sigma6[i] = sigma6_def;
305 sigma2[i] = sigma2_def;
307 if (sc_r_power == 6.0)
309 sigma_pow[i] = sigma6[i];
310 sigma_powm2[i] = sigma6[i]/sigma2[i];
312 else if (sc_r_power == 48.0)
314 sigma_pow[i] = sigma6[i]*sigma6[i]; /* sigma^12 */
315 sigma_pow[i] = sigma_pow[i]*sigma_pow[i]; /* sigma^24 */
316 sigma_pow[i] = sigma_pow[i]*sigma_pow[i]; /* sigma^48 */
317 sigma_powm2[i] = sigma_pow[i]/sigma2[i];
320 { /* not really supported as input, but in here for testing the general case*/
321 sigma_pow[i] = pow(sigma2[i], sc_r_power/2);
322 sigma_powm2[i] = sigma_pow[i]/(sigma2[i]);
326 /* only use softcore if one of the states has a zero endstate - softcore is for avoiding infinities!*/
327 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);
364 n1C = tab_elemsize*n0;
370 n1V = tab_elemsize*n0;
373 /* With Ewald and soft-core we should put the cut-off on r,
374 * not on the soft-cored rC, as the real-space and
375 * reciprocal space contributions should (almost) cancel.
378 !(bExactElecCutoff &&
379 ((icoul != GMX_NBKERNEL_ELEC_EWALD && rC >= rcoulomb) ||
380 (icoul == GMX_NBKERNEL_ELEC_EWALD && r >= rcoulomb))))
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;
411 case GMX_NBKERNEL_ELEC_GENERALIZEDBORN:
412 gmx_fatal(FARGS, "Free energy and GB not implemented.\n");
415 case GMX_NBKERNEL_ELEC_NONE:
421 gmx_incons("Invalid icoul in free energy kernel");
425 if (fr->coulomb_modifier == eintmodPOTSWITCH)
428 d = (d > 0.0) ? d : 0.0;
430 sw = 1.0+d2*d*(swV3+d*(swV4+d*swV5));
431 dsw = d2*(swF2+d*(swF3+d*swF4));
434 FscalC[i] = FscalC[i]*sw + Vcoul[i]*dsw;
438 if ((c6[i] != 0 || c12[i] != 0) &&
439 !(bExactVdwCutoff && rV >= rvdw))
443 case GMX_NBKERNEL_VDW_LENNARDJONES:
445 if (sc_r_power == 6.0)
451 rinv6 = pow(rinvV, 6.0);
454 Vvdw12 = c12[i]*rinv6*rinv6;
455 if (fr->vdw_modifier == eintmodPOTSHIFT)
457 Vvdw[i] = ( (Vvdw12-c12[i]*sh_invrc6*sh_invrc6)*(1.0/12.0)
458 -(Vvdw6-c6[i]*sh_invrc6)*(1.0/6.0));
462 Vvdw[i] = Vvdw12*(1.0/12.0)-Vvdw6*(1.0/6.0);
464 FscalV[i] = (Vvdw12-Vvdw6)*rpinvV;
467 case GMX_NBKERNEL_VDW_BUCKINGHAM:
468 gmx_fatal(FARGS, "Buckingham free energy not supported.");
471 case GMX_NBKERNEL_VDW_CUBICSPLINETABLE:
477 Geps = epsV*VFtab[nnn+2];
478 Heps2 = eps2V*VFtab[nnn+3];
481 FF = Fp+Geps+2.0*Heps2;
483 FscalV[i] -= c6[i]*tabscale*FF*rV*rpinvV;
488 Geps = epsV*VFtab[nnn+6];
489 Heps2 = eps2V*VFtab[nnn+7];
492 FF = Fp+Geps+2.0*Heps2;
493 Vvdw[i] += c12[i]*VV;
494 FscalV[i] -= c12[i]*tabscale*FF*rV*rpinvV;
497 case GMX_NBKERNEL_VDW_NONE:
503 gmx_incons("Invalid ivdw in free energy kernel");
507 if (fr->vdw_modifier == eintmodPOTSWITCH)
510 d = (d > 0.0) ? d : 0.0;
512 sw = 1.0+d2*d*(swV3+d*(swV4+d*swV5));
513 dsw = d2*(swF2+d*(swF3+d*swF4));
516 FscalV[i] = FscalV[i]*sw + Vvdw[i]*dsw;
518 FscalV[i] = (rV < rvdw) ? FscalV[i] : 0.0;
519 Vvdw[i] = (rV < rvdw) ? Vvdw[i] : 0.0;
527 if (icoul == GMX_NBKERNEL_ELEC_EWALD &&
528 !(bExactElecCutoff && r >= rcoulomb))
530 /* because we compute the softcore normally,
531 we have to remove the ewald short range portion. Done outside of
532 the states loop because this part doesn't depend on the scaled R */
535 /* Relative accuracy at R_ERF_R_INACC of 3e-10 */
536 #define R_ERF_R_INACC 0.006
538 /* Relative accuracy at R_ERF_R_INACC of 2e-5 */
539 #define R_ERF_R_INACC 0.1
541 if (ewc*r > R_ERF_R_INACC)
543 VV = gmx_erf(ewc*r)*rinv;
544 FF = rinv*rinv*(VV - ewc*M_2_SQRTPI*exp(-ewc*ewc*rsq));
549 FF = ewc*ewc*ewc*M_2_SQRTPI*(2.0/3.0 - 0.4*ewc*ewc*rsq);
552 for (i = 0; i < NSTATES; i++)
554 vctot -= LFC[i]*qq[i]*VV;
555 Fscal -= LFC[i]*qq[i]*FF;
556 dvdl_coul -= (DLF[i]*qq[i])*VV;
560 /* Assemble A and B states */
561 for (i = 0; i < NSTATES; i++)
563 vctot += LFC[i]*Vcoul[i];
564 vvtot += LFV[i]*Vvdw[i];
566 Fscal += LFC[i]*FscalC[i]*rpm2;
567 Fscal += LFV[i]*FscalV[i]*rpm2;
569 dvdl_coul += Vcoul[i]*DLF[i] + LFC[i]*alpha_coul_eff*dlfac_coul[i]*FscalC[i]*sigma_pow[i];
570 dvdl_vdw += Vvdw[i]*DLF[i] + LFV[i]*alpha_vdw_eff*dlfac_vdw[i]*FscalV[i]*sigma_pow[i];
582 f[j3+1] = f[j3+1] - ty;
583 f[j3+2] = f[j3+2] - tz;
589 f[ii3] = f[ii3] + fix;
590 f[ii3+1] = f[ii3+1] + fiy;
591 f[ii3+2] = f[ii3+2] + fiz;
592 fshift[is3] = fshift[is3] + fix;
593 fshift[is3+1] = fshift[is3+1] + fiy;
594 fshift[is3+2] = fshift[is3+2] + fiz;
597 Vc[ggid] = Vc[ggid] + vctot;
598 Vv[ggid] = Vv[ggid] + vvtot;
601 dvdl[efptCOUL] += dvdl_coul;
602 dvdl[efptVDW] += dvdl_vdw;
604 /* Estimate flops, average for free energy stuff:
605 * 12 flops per outer iteration
606 * 150 flops per inner iteration
608 inc_nrnb(nrnb, eNR_NBKERNEL_FREE_ENERGY, nlist->nri*12 + nlist->jindex[n]*150);
612 nb_free_energy_evaluate_single(real r2, real sc_r_power, real alpha_coul, real alpha_vdw,
613 real tabscale, real *vftab,
614 real qqA, real c6A, real c12A, real qqB, real c6B, real c12B,
615 real LFC[2], real LFV[2], real DLF[2],
616 real lfac_coul[2], real lfac_vdw[2], real dlfac_coul[2], real dlfac_vdw[2],
617 real sigma6_def, real sigma6_min, real sigma2_def, real sigma2_min,
618 real *velectot, real *vvdwtot, real *dvdl)
620 real r, rp, rpm2, rtab, eps, eps2, Y, F, Geps, Heps2, Fp, VV, FF, fscal;
621 real qq[2], c6[2], c12[2], sigma6[2], sigma2[2], sigma_pow[2], sigma_powm2[2];
622 real alpha_coul_eff, alpha_vdw_eff, dvdl_coul, dvdl_vdw;
623 real rpinv, r_coul, r_vdw, velecsum, vvdwsum;
624 real fscal_vdw[2], fscal_elec[2];
625 real velec[2], vvdw[2];
635 if (sc_r_power == 6.0)
637 rpm2 = r2*r2; /* r4 */
638 rp = rpm2*r2; /* r6 */
640 else if (sc_r_power == 48.0)
642 rp = r2*r2*r2; /* r6 */
643 rp = rp*rp; /* r12 */
644 rp = rp*rp; /* r24 */
645 rp = rp*rp; /* r48 */
646 rpm2 = rp/r2; /* r46 */
650 rp = pow(r2, 0.5*sc_r_power); /* not currently supported as input, but can handle it */
654 /* Loop over state A(0) and B(1) */
655 for (i = 0; i < 2; i++)
657 if ((c6[i] > 0) && (c12[i] > 0))
659 /* The c6 & c12 coefficients now contain the constants 6.0 and 12.0, respectively.
660 * Correct for this by multiplying with (1/12.0)/(1/6.0)=6.0/12.0=0.5.
662 sigma6[i] = 0.5*c12[i]/c6[i];
663 sigma2[i] = pow(0.5*c12[i]/c6[i], 1.0/3.0);
664 /* should be able to get rid of this ^^^ internal pow call eventually. Will require agreement on
665 what data to store externally. Can't be fixed without larger scale changes, so not 4.6 */
666 if (sigma6[i] < sigma6_min) /* for disappearing coul and vdw with soft core at the same time */
668 sigma6[i] = sigma6_min;
669 sigma2[i] = sigma2_min;
674 sigma6[i] = sigma6_def;
675 sigma2[i] = sigma2_def;
677 if (sc_r_power == 6.0)
679 sigma_pow[i] = sigma6[i];
680 sigma_powm2[i] = sigma6[i]/sigma2[i];
682 else if (sc_r_power == 48.0)
684 sigma_pow[i] = sigma6[i]*sigma6[i]; /* sigma^12 */
685 sigma_pow[i] = sigma_pow[i]*sigma_pow[i]; /* sigma^24 */
686 sigma_pow[i] = sigma_pow[i]*sigma_pow[i]; /* sigma^48 */
687 sigma_powm2[i] = sigma_pow[i]/sigma2[i];
690 { /* not really supported as input, but in here for testing the general case*/
691 sigma_pow[i] = pow(sigma2[i], sc_r_power/2);
692 sigma_powm2[i] = sigma_pow[i]/(sigma2[i]);
696 /* only use softcore if one of the states has a zero endstate - softcore is for avoiding infinities!*/
697 if ((c12[0] > 0) && (c12[1] > 0))
704 alpha_vdw_eff = alpha_vdw;
705 alpha_coul_eff = alpha_coul;
708 /* Loop over A and B states again */
709 for (i = 0; i < 2; i++)
716 /* Only spend time on A or B state if it is non-zero */
717 if ( (qq[i] != 0) || (c6[i] != 0) || (c12[i] != 0) )
720 rpinv = 1.0/(alpha_coul_eff*lfac_coul[i]*sigma_pow[i]+rp);
721 r_coul = pow(rpinv, -1.0/sc_r_power);
723 /* Electrostatics table lookup data */
724 rtab = r_coul*tabscale;
732 Geps = eps*vftab[ntab+2];
733 Heps2 = eps2*vftab[ntab+3];
736 FF = Fp+Geps+2.0*Heps2;
738 fscal_elec[i] = -qq[i]*FF*r_coul*rpinv*tabscale;
741 rpinv = 1.0/(alpha_vdw_eff*lfac_vdw[i]*sigma_pow[i]+rp);
742 r_vdw = pow(rpinv, -1.0/sc_r_power);
743 /* Vdw table lookup data */
744 rtab = r_vdw*tabscale;
752 Geps = eps*vftab[ntab+6];
753 Heps2 = eps2*vftab[ntab+7];
756 FF = Fp+Geps+2.0*Heps2;
758 fscal_vdw[i] = -c6[i]*FF;
763 Geps = eps*vftab[ntab+10];
764 Heps2 = eps2*vftab[ntab+11];
767 FF = Fp+Geps+2.0*Heps2;
768 vvdw[i] += c12[i]*VV;
769 fscal_vdw[i] -= c12[i]*FF;
770 fscal_vdw[i] *= r_vdw*rpinv*tabscale;
773 /* Now we have velec[i], vvdw[i], and fscal[i] for both states */
774 /* Assemble A and B states */
780 for (i = 0; i < 2; i++)
782 velecsum += LFC[i]*velec[i];
783 vvdwsum += LFV[i]*vvdw[i];
785 fscal += (LFC[i]*fscal_elec[i]+LFV[i]*fscal_vdw[i])*rpm2;
787 dvdl_coul += velec[i]*DLF[i] + LFC[i]*alpha_coul_eff*dlfac_coul[i]*fscal_elec[i]*sigma_pow[i];
788 dvdl_vdw += vvdw[i]*DLF[i] + LFV[i]*alpha_vdw_eff*dlfac_vdw[i]*fscal_vdw[i]*sigma_pow[i];
791 dvdl[efptCOUL] += dvdl_coul;
792 dvdl[efptVDW] += dvdl_vdw;
794 *velectot = velecsum;