1 // clang-format off
2 /* ----------------------------------------------------------------------
3    LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
4    https://www.lammps.org/, Sandia National Laboratories
5    Steve Plimpton, sjplimp@sandia.gov
6 
7    Copyright (2003) Sandia Corporation.  Under the terms of Contract
8    DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
9    certain rights in this software.  This software is distributed under
10    the GNU General Public License.
11 
12    See the README file in the top-level LAMMPS directory.
13 ------------------------------------------------------------------------- */
14 
15 /* ----------------------------------------------------------------------
16    Contributing author: Anders Hafreager (UiO), andershaf@gmail.com
17 ------------------------------------------------------------------------- */
18 
19 #include "pair_vashishta_table.h"
20 
21 #include "atom.h"
22 #include "error.h"
23 #include "force.h"
24 #include "memory.h"
25 #include "neigh_list.h"
26 
27 using namespace LAMMPS_NS;
28 
29 /* ---------------------------------------------------------------------- */
30 
PairVashishtaTable(LAMMPS * lmp)31 PairVashishtaTable::PairVashishtaTable(LAMMPS *lmp) : PairVashishta(lmp)
32 {
33   forceTable = nullptr;
34   potentialTable = nullptr;
35 }
36 
37 /* ----------------------------------------------------------------------
38    check if allocated, since class can be destructed when incomplete
39 ------------------------------------------------------------------------- */
40 
~PairVashishtaTable()41 PairVashishtaTable::~PairVashishtaTable()
42 {
43   memory->destroy(forceTable);
44   memory->destroy(potentialTable);
45 }
46 
47 /* ---------------------------------------------------------------------- */
48 
compute(int eflag,int vflag)49 void PairVashishtaTable::compute(int eflag, int vflag)
50 {
51   int i,j,k,ii,jj,kk,inum,jnum,jnumm1;
52   int itype,jtype,ktype,ijparam,ikparam,ijkparam;
53   tagint itag,jtag;
54   double xtmp,ytmp,ztmp,delx,dely,delz,evdwl,fpair;
55   double rsq,rsq1,rsq2;
56   double delr1[3],delr2[3],fj[3],fk[3];
57   int *ilist,*jlist,*numneigh,**firstneigh;
58 
59   evdwl = 0.0;
60   ev_init(eflag,vflag);
61 
62   double **x = atom->x;
63   double **f = atom->f;
64   tagint *tag = atom->tag;
65   int *type = atom->type;
66   int nlocal = atom->nlocal;
67   int newton_pair = force->newton_pair;
68   const double cutshortsq = r0max*r0max;
69 
70   inum = list->inum;
71   ilist = list->ilist;
72   numneigh = list->numneigh;
73   firstneigh = list->firstneigh;
74 
75   double fxtmp,fytmp,fztmp;
76 
77   // loop over full neighbor list of my atoms
78 
79   for (ii = 0; ii < inum; ii++) {
80     i = ilist[ii];
81     itag = tag[i];
82     itype = map[type[i]];
83     xtmp = x[i][0];
84     ytmp = x[i][1];
85     ztmp = x[i][2];
86     fxtmp = fytmp = fztmp = 0.0;
87 
88     // two-body interactions, skip half of them
89 
90     jlist = firstneigh[i];
91     jnum = numneigh[i];
92     int numshort = 0;
93 
94     for (jj = 0; jj < jnum; jj++) {
95       j = jlist[jj];
96       j &= NEIGHMASK;
97 
98       delx = xtmp - x[j][0];
99       dely = ytmp - x[j][1];
100       delz = ztmp - x[j][2];
101       rsq = delx*delx + dely*dely + delz*delz;
102 
103       if (rsq < cutshortsq) {
104         neighshort[numshort++] = j;
105         if (numshort >= maxshort) {
106           maxshort += maxshort/2;
107           memory->grow(neighshort,maxshort,"pair:neighshort");
108         }
109       }
110 
111       jtag = tag[j];
112       if (itag > jtag) {
113         if ((itag+jtag) % 2 == 0) continue;
114       } else if (itag < jtag) {
115         if ((itag+jtag) % 2 == 1) continue;
116       } else {
117         if (x[j][2] < ztmp) continue;
118         if (x[j][2] == ztmp && x[j][1] < ytmp) continue;
119         if (x[j][2] == ztmp && x[j][1] == ytmp && x[j][0] < xtmp) continue;
120       }
121 
122       jtype = map[type[j]];
123       ijparam = elem3param[itype][jtype][jtype];
124       if (rsq >= params[ijparam].cutsq) continue;
125 
126       twobody_table(params[ijparam],rsq,fpair,eflag,evdwl);
127 
128       fxtmp += delx*fpair;
129       fytmp += dely*fpair;
130       fztmp += delz*fpair;
131       f[j][0] -= delx*fpair;
132       f[j][1] -= dely*fpair;
133       f[j][2] -= delz*fpair;
134 
135       if (evflag) ev_tally(i,j,nlocal,newton_pair,
136                    evdwl,0.0,fpair,delx,dely,delz);
137     }
138 
139     jnumm1 = numshort - 1;
140 
141     for (jj = 0; jj < jnumm1; jj++) {
142       j = neighshort[jj];
143       jtype = map[type[j]];
144       ijparam = elem3param[itype][jtype][jtype];
145       delr1[0] = x[j][0] - xtmp;
146       delr1[1] = x[j][1] - ytmp;
147       delr1[2] = x[j][2] - ztmp;
148       rsq1 = delr1[0]*delr1[0] + delr1[1]*delr1[1] + delr1[2]*delr1[2];
149       if (rsq1 >= params[ijparam].cutsq2) continue;
150 
151       double fjxtmp,fjytmp,fjztmp;
152       fjxtmp = fjytmp = fjztmp = 0.0;
153 
154       for (kk = jj+1; kk < numshort; kk++) {
155         k = neighshort[kk];
156         ktype = map[type[k]];
157         ikparam = elem3param[itype][ktype][ktype];
158         ijkparam = elem3param[itype][jtype][ktype];
159 
160         delr2[0] = x[k][0] - xtmp;
161         delr2[1] = x[k][1] - ytmp;
162         delr2[2] = x[k][2] - ztmp;
163         rsq2 = delr2[0]*delr2[0] + delr2[1]*delr2[1] + delr2[2]*delr2[2];
164         if (rsq2 >= params[ikparam].cutsq2) continue;
165 
166         threebody(&params[ijparam],&params[ikparam],&params[ijkparam],
167                   rsq1,rsq2,delr1,delr2,fj,fk,eflag,evdwl);
168 
169         fxtmp -= fj[0] + fk[0];
170         fytmp -= fj[1] + fk[1];
171         fztmp -= fj[2] + fk[2];
172         fjxtmp += fj[0];
173         fjytmp += fj[1];
174         fjztmp += fj[2];
175         f[k][0] += fk[0];
176         f[k][1] += fk[1];
177         f[k][2] += fk[2];
178 
179         if (evflag) ev_tally3(i,j,k,evdwl,0.0,fj,fk,delr1,delr2);
180       }
181       f[j][0] += fjxtmp;
182       f[j][1] += fjytmp;
183       f[j][2] += fjztmp;
184     }
185     f[i][0] += fxtmp;
186     f[i][1] += fytmp;
187     f[i][2] += fztmp;
188   }
189 
190   if (vflag_fdotr) virial_fdotr_compute();
191 }
192 
193 /* ---------------------------------------------------------------------- */
194 
twobody_table(const Param & param,double rsq,double & fforce,int eflag,double & eng)195 void PairVashishtaTable::twobody_table(const Param &param, double rsq,
196                                        double &fforce, int eflag, double &eng)
197 {
198   // use analytic form if rsq is inside inner cutoff
199 
200   if (rsq < tabinnersq) {
201     Param *pparam = const_cast<Param *> (&param);
202     PairVashishta::twobody(pparam,rsq,fforce,eflag,eng);
203     return;
204   }
205 
206   // double -> int will only keep the 0.xxxx part
207 
208   const int tableIndex = (rsq - tabinnersq)*oneOverDeltaR2;
209   const double fraction = (rsq - tabinnersq)*oneOverDeltaR2 - tableIndex;
210 
211   // force/energy are linearly interpolated between two adjacent values
212 
213   double force0 = forceTable[param.ielement][param.jelement][tableIndex];
214   double force1 = forceTable[param.ielement][param.jelement][tableIndex+1];
215   fforce = (1.0 - fraction)*force0 + fraction*force1;
216 
217   if (evflag) {
218     double energy0 = potentialTable[param.ielement][param.jelement][tableIndex];
219     double energy1 = potentialTable[param.ielement][param.jelement]
220       [tableIndex+1];
221     eng = (1.0 - fraction)*energy0 + fraction*energy1;
222   }
223 }
224 
225 /* ----------------------------------------------------------------------
226    global settings
227 ------------------------------------------------------------------------- */
228 
settings(int narg,char ** arg)229 void PairVashishtaTable::settings(int narg, char **arg)
230 {
231   if (narg != 2) error->all(FLERR,"Illegal pair_style command");
232 
233   ntable = utils::inumeric(FLERR,arg[0],false,lmp);
234   tabinner = utils::numeric(FLERR,arg[1],false,lmp);
235 
236   if (tabinner <= 0.0)
237     error->all(FLERR,"Illegal inner cutoff for tabulation");
238 }
239 
240 /* ---------------------------------------------------------------------- */
241 
setup_params()242 void PairVashishtaTable::setup_params()
243 {
244   PairVashishta::setup_params();
245 
246   create_tables();
247 }
248 
249 /* ---------------------------------------------------------------------- */
250 
create_tables()251 void PairVashishtaTable::create_tables()
252 {
253   memory->destroy(forceTable);
254   memory->destroy(potentialTable);
255   forceTable = nullptr;
256   potentialTable = nullptr;
257 
258   tabinnersq = tabinner*tabinner;
259 
260   deltaR2 = (cutmax*cutmax - tabinnersq) / (ntable-1);
261   oneOverDeltaR2 = 1.0/deltaR2;
262 
263   memory->create(forceTable,nelements,nelements,ntable+1,
264                  "pair:vashishta:forceTable");
265   memory->create(potentialTable,nelements,nelements,ntable+1,
266                  "pair:vashishta:potentialTable");
267 
268   // tabulalate energy/force via analytic twobody() in parent
269 
270   int i,j,idx;
271   double rsq,fpair,eng;
272 
273   for (i = 0; i < nelements; i++) {
274     for (j = 0; j < nelements; j++) {
275       int ijparam = elem3param[i][j][j];
276       for (idx = 0; idx <= ntable; idx++) {
277         rsq = tabinnersq + idx*deltaR2;
278         PairVashishta::twobody(&params[ijparam],rsq,fpair,1,eng);
279         forceTable[i][j][idx] = fpair;
280         potentialTable[i][j][idx] = eng;
281       }
282     }
283   }
284 }
285 
286 /* ----------------------------------------------------------------------
287    memory usage of tabulation arrays
288 ------------------------------------------------------------------------- */
289 
memory_usage()290 double PairVashishtaTable::memory_usage()
291 {
292   return (double)2*nelements*nelements*sizeof(double)*ntable;
293 }
294