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(¶ms[ijparam],¶ms[ikparam],¶ms[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 ¶m, 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 *> (¶m);
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(¶ms[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