Files
lammps/src/AMOEBA/amoeba_hal.cpp
2022-03-10 16:41:58 -07:00

214 lines
5.4 KiB
C++

/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "pair_amoeba.h"
#include <cmath>
#include "atom.h"
#include "neigh_list.h"
#include "error.h"
using namespace LAMMPS_NS;
enum{VDWL,REPULSE,QFER,DISP,MPOLE,POLAR,USOLV,DISP_LONG,MPOLE_LONG,POLAR_LONG};
/* ----------------------------------------------------------------------
hal = buffered 14-7 Vdwl interactions
adapted from Tinker ehal1c() routine
------------------------------------------------------------------------- */
void PairAmoeba::hal()
{
int i,j,ii,jj,itype,jtype,iclass,jclass,iv,jv;
int special_which;
double e,de,eps,rdn;
double fgrp,rv,rv7;
double xi,yi,zi;
double xr,yr,zr;
double redi,rediv;
double redj,redjv;
double dedx,dedy,dedz;
double rho,rho6,rho7;
double tau,tau7,scal;
double s1,s2,t1,t2;
double dt1drho,dt2drho;
double dtau,gtau;
double taper,dtaper;
double rik,rik2,rik3;
double rik4,rik5;
double rik6,rik7;
double vxx,vyy,vzz;
double vyx,vzx,vzy;
double factor_hal;
double vir[6];
int inum,jnum;
int *ilist,*jlist,*numneigh,**firstneigh;
// set cutoffs and taper coeffs
choose(VDWL);
// owned atoms
double **x = atom->x;
double **f = atom->f;
int nlocal = atom->nlocal;
// neigh list
inum = list->inum;
ilist = list->ilist;
numneigh = list->numneigh;
firstneigh = list->firstneigh;
// find van der Waals energy and derivatives via neighbor list
for (ii = 0; ii < inum; ii++) {
i = ilist[ii];
itype = amtype[i];
iclass = amtype2class[itype];
jlist = firstneigh[i];
jnum = numneigh[i];
redi = kred[iclass];
rediv = 1.0 - redi;
xi = xred[i][0];
yi = xred[i][1];
zi = xred[i][2];
for (jj = 0; jj < jnum; jj++) {
j = jlist[jj];
special_which = sbmask15(j);
factor_hal = special_hal[special_which];
if (factor_hal == 0.0) continue;
j &= NEIGHMASK15;
xr = xi - xred[j][0];
yr = yi - xred[j][1];
zr = zi - xred[j][2];
rik2 = xr*xr + yr*yr + zr*zr;
if (rik2 > off2) continue;
// compute the energy contribution for this interaction
jtype = amtype[j];
jclass = amtype2class[jtype];
// check for an interaction distance less than the cutoff
// special_which = 3 is a 1-4 neighbor with its own sigma,epsilon
rik = sqrt(rik2);
rv = radmin[iclass][jclass];
eps = epsilon[iclass][jclass];
if (special_which == 3) {
rv = radmin4[iclass][jclass];
eps = epsilon4[iclass][jclass];
}
eps *= factor_hal;
rv7 = pow(rv,7.0);
rik6 = pow(rik2,3.0);
rik7 = rik6 * rik;
rho = rik7 + ghal*rv7;
tau = (dhal+1.0) / (rik + dhal*rv);
tau7 = pow(tau,7.0);
dtau = tau / (dhal+1.0);
gtau = eps*tau7*rik6*(ghal+1.0)*pow(rv7/rho,2.0);
e = eps*tau7*rv7*((ghal+1.0)*rv7/rho-2.0);
de = -7.0 * (dtau*e+gtau);
// use energy switching if near the cutoff distance
if (rik2 > cut2) {
rik3 = rik2 * rik;
rik4 = rik2 * rik2;
rik5 = rik2 * rik3;
taper = c5*rik5 + c4*rik4 + c3*rik3 + c2*rik2 + c1*rik + c0;
dtaper = 5.0*c5*rik4 + 4.0*c4*rik3 + 3.0*c3*rik2 + 2.0*c2*rik + c1;
de = e*dtaper + de*taper;
e *= taper;
}
ehal += e;
// find the chain rule terms for derivative components
de = de / rik;
dedx = de * xr;
dedy = de * yr;
dedz = de * zr;
// increment the total van der Waals energy and derivatives
// if jv < 0, trigger an error, needed H-bond partner is missing
iv = ired2local[i];
jv = ired2local[j];
if (jv < 0)
error->one(FLERR,"AMOEBA hal cannot find H bond partner - "
"ghost comm is too short");
if (i == iv) {
f[i][0] += dedx;
f[i][1] += dedy;
f[i][2] += dedz;
} else {
f[i][0] += dedx*redi;
f[i][1] += dedy*redi;
f[i][2] += dedz*redi;
f[iv][0] += dedx*rediv;
f[iv][1] += dedy*rediv;
f[iv][2] += dedz*rediv;
}
if (j == jv) {
f[j][0] -= dedx;
f[j][1] -= dedy;
f[j][2] -= dedz;
} else {
redj = kred[jclass];
redjv = 1.0 - redj;
f[j][0] -= dedx*redj;
f[j][1] -= dedy*redj;
f[j][2] -= dedz*redj;
f[jv][0] -= dedx*redjv;
f[jv][1] -= dedy*redjv;
f[jv][2] -= dedz*redjv;
}
// increment the internal virial tensor components
vxx = xr * dedx;
vyx = yr * dedx;
vzx = zr * dedx;
vyy = yr * dedy;
vzy = zr * dedy;
vzz = zr * dedz;
virhal[0] += vxx;
virhal[1] += vyy;
virhal[2] += vzz;
virhal[3] += vyx;
virhal[4] += vzx;
virhal[5] += vzy;
// energy = e
// virial = 6-vec vir
// NOTE: add tally function
if (evflag) {
}
}
}
}