coulombLennardJones.cc 4.7 KB
Newer Older
1
{
2
#if USE_EWALD
3
    unsigned int includeInteraction = (!isExcluded && r2 < CUTOFF_SQUARED);
Peter Eastman's avatar
Peter Eastman committed
4
5
    const real alphaR = EWALD_ALPHA*r;
    const real expAlphaRSqr = EXP(-alphaR*alphaR);
6
#if HAS_COULOMB
7
    const real prefactor = ONE_4PI_EPS0*CHARGE1*CHARGE2*invR;
8
9
10
#else
    const real prefactor = 0.0f;
#endif
11

12
#ifdef USE_DOUBLE_PRECISION
Peter Eastman's avatar
Peter Eastman committed
13
    const real erfcAlphaR = erfc(alphaR);
14
#else
Peter Eastman's avatar
Peter Eastman committed
15
16
    // This approximation for erfc is from Abramowitz and Stegun (1964) p. 299.  They cite the following as
    // the original source: C. Hastings, Jr., Approximations for Digital Computers (1955).  It has a maximum
17
    // error of 1.5e-7.
18

19
20
    const real t = RECIP(1.0f+0.3275911f*alphaR);
    const real erfcAlphaR = (0.254829592f+(-0.284496736f+(1.421413741f+(-1.453152027f+1.061405429f*t)*t)*t)*t)*t*expAlphaRSqr;
21
#endif
Peter Eastman's avatar
Peter Eastman committed
22
    real tempForce = 0.0f;
23
#if HAS_LENNARD_JONES
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
    real sig = SIGMA_EPSILON1.x + SIGMA_EPSILON2.x;
    real sig2 = invR*sig;
    sig2 *= sig2;
    real sig6 = sig2*sig2*sig2;
    real eps = SIGMA_EPSILON1.y*SIGMA_EPSILON2.y;
    real epssig6 = sig6*eps;
    tempForce = epssig6*(12.0f*sig6 - 6.0f);
    real ljEnergy = epssig6*(sig6 - 1.0f);
    #if USE_LJ_SWITCH
    if (r > LJ_SWITCH_CUTOFF) {
        real x = r-LJ_SWITCH_CUTOFF;
        real switchValue = 1+x*x*x*(LJ_SWITCH_C3+x*(LJ_SWITCH_C4+x*LJ_SWITCH_C5));
        real switchDeriv = x*x*(3*LJ_SWITCH_C3+x*(4*LJ_SWITCH_C4+x*5*LJ_SWITCH_C5));
        tempForce = tempForce*switchValue - ljEnergy*switchDeriv*r;
        ljEnergy *= switchValue;
Peter Eastman's avatar
Peter Eastman committed
39
    }
40
    #endif
41
#if DO_LJPME
42
43
    // The multiplicative term to correct for the multiplicative terms that are always
    // present in reciprocal space.
44
45
46
#if defined(USE_HIP)
    const real dar2 = EWALD_DISPERSION_ALPHA*EWALD_DISPERSION_ALPHA*r2;
#else
47
48
    const real dispersionAlphaR = EWALD_DISPERSION_ALPHA*r;
    const real dar2 = dispersionAlphaR*dispersionAlphaR;
49
#endif
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
    const real dar4 = dar2*dar2;
    const real dar6 = dar4*dar2;
    const real invR2 = invR*invR;
    const real expDar2 = EXP(-dar2);
    const float2 sigExpProd = SIGMA_EPSILON1*SIGMA_EPSILON2;
    const real c6 = 64*sigExpProd.x*sigExpProd.x*sigExpProd.x*sigExpProd.y;
    const real coef = invR2*invR2*invR2*c6;
    const real eprefac = 1.0f + dar2 + 0.5f*dar4;
    const real dprefac = eprefac + dar6/6.0f;
    // The multiplicative grid term
    ljEnergy += coef*(1.0f - expDar2*eprefac);
    tempForce += 6.0f*coef*(1.0f - expDar2*dprefac);
    // The potential shift accounts for the step at the cutoff introduced by the
    // transition from additive to multiplicative combintion rules and is only
    // needed for the real (not excluded) terms.  By addin these terms to ljEnergy
    // instead of tempEnergy here, the includeInteraction mask is correctly applied.
    sig2 = sig*sig;
    sig6 = sig2*sig2*sig2*INVCUT6;
    epssig6 = eps*sig6;
    // The additive part of the potential shift
    ljEnergy += epssig6*(1.0f - sig6);
    // The multiplicative part of the potential shift
    ljEnergy += MULTSHIFT6*c6;
73
#endif
74
75
    tempForce += prefactor*(erfcAlphaR+alphaR*expAlphaRSqr*TWO_OVER_SQRT_PI);
    tempEnergy += includeInteraction ? ljEnergy + prefactor*erfcAlphaR : 0;
76
#else
77
78
    tempForce = prefactor*(erfcAlphaR+alphaR*expAlphaRSqr*TWO_OVER_SQRT_PI);
    tempEnergy += includeInteraction ? prefactor*erfcAlphaR : 0;
79
#endif
80
    dEdR += includeInteraction ? tempForce*invR*invR : 0;
81
82
83
84
85
86
87
#else
#ifdef USE_CUTOFF
    unsigned int includeInteraction = (!isExcluded && r2 < CUTOFF_SQUARED);
#else
    unsigned int includeInteraction = (!isExcluded);
#endif
    real tempForce = 0.0f;
88
#if HAS_LENNARD_JONES
89
    real sig = SIGMA_EPSILON1.x + SIGMA_EPSILON2.x;
90
91
92
    real sig2 = invR*sig;
    sig2 *= sig2;
    real sig6 = sig2*sig2*sig2;
93
    real epssig6 = sig6*(SIGMA_EPSILON1.y*SIGMA_EPSILON2.y);
94
    tempForce = epssig6*(12.0f*sig6 - 6.0f);
95
96
97
98
99
100
101
102
103
104
105
    real ljEnergy = includeInteraction ? epssig6*(sig6 - 1) : 0;
    #if USE_LJ_SWITCH
    if (r > LJ_SWITCH_CUTOFF) {
        real x = r-LJ_SWITCH_CUTOFF;
        real switchValue = 1+x*x*x*(LJ_SWITCH_C3+x*(LJ_SWITCH_C4+x*LJ_SWITCH_C5));
        real switchDeriv = x*x*(3*LJ_SWITCH_C3+x*(4*LJ_SWITCH_C4+x*5*LJ_SWITCH_C5));
        tempForce = tempForce*switchValue - ljEnergy*switchDeriv*r;
        ljEnergy *= switchValue;
    }
    #endif
    tempEnergy += ljEnergy;
106
#endif
107
108
#if HAS_COULOMB
  #ifdef USE_CUTOFF
109
    const real prefactor = ONE_4PI_EPS0*CHARGE1*CHARGE2;
110
111
112
    tempForce += prefactor*(invR - 2.0f*REACTION_FIELD_K*r2);
    tempEnergy += includeInteraction ? prefactor*(invR + REACTION_FIELD_K*r2 - REACTION_FIELD_C) : 0;
  #else
113
    const real prefactor = ONE_4PI_EPS0*CHARGE1*CHARGE2*invR;
114
115
116
117
118
    tempForce += prefactor;
    tempEnergy += includeInteraction ? prefactor : 0;
  #endif
#endif
    dEdR += includeInteraction ? tempForce*invR*invR : 0;
119
#endif
120
}