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:
17             Rodolfo Paula Leite (Unicamp/Brazil) - pl.rodolfo@gmail.com
18             Maurice de Koning (Unicamp/Brazil) - dekoning@ifi.unicamp.br
19  ------------------------------------------------------------------------- */
20 
21 #include "pair_ufm_opt.h"
22 
23 #include <cmath>
24 #include "atom.h"
25 #include "force.h"
26 #include "neigh_list.h"
27 
28 using namespace LAMMPS_NS;
29 
30 /* ---------------------------------------------------------------------- */
31 
PairUFMOpt(LAMMPS * lmp)32 PairUFMOpt::PairUFMOpt(LAMMPS *lmp) : PairUFM(lmp) {}
33 
34 /* ---------------------------------------------------------------------- */
35 
compute(int eflag,int vflag)36 void PairUFMOpt::compute(int eflag, int vflag)
37 {
38   ev_init(eflag,vflag);
39 
40   if (evflag) {
41     if (eflag) {
42       if (force->newton_pair) return eval<1,1,1>();
43       else return eval<1,1,0>();
44     } else {
45       if (force->newton_pair) return eval<1,0,1>();
46       else return eval<1,0,0>();
47     }
48   } else {
49     if (force->newton_pair) return eval<0,0,1>();
50     else return eval<0,0,0>();
51   }
52 }
53 
54 /* ---------------------------------------------------------------------- */
55 
56 template < int EVFLAG, int EFLAG, int NEWTON_PAIR >
eval()57 void PairUFMOpt::eval()
58 {
59   typedef struct { double x,y,z; } vec3_t;
60 
61   typedef struct {
62     double cutsq,uf1,uf2,uf3,scale,offset;
63     double _pad[2];
64   } fast_alpha_t;
65 
66   int i,j,ii,jj,inum,jnum,itype,jtype,sbindex;
67   double factor_lj;
68   double evdwl = 0.0;
69 
70   double** _noalias x = atom->x;
71   double** _noalias f = atom->f;
72   int* _noalias type = atom->type;
73   int nlocal = atom->nlocal;
74   double* _noalias special_lj = force->special_lj;
75 
76   inum = list->inum;
77   int* _noalias ilist = list->ilist;
78   int** _noalias firstneigh = list->firstneigh;
79   int* _noalias numneigh = list->numneigh;
80 
81   vec3_t* _noalias xx = (vec3_t*)x[0];
82   vec3_t* _noalias ff = (vec3_t*)f[0];
83 
84   int ntypes = atom->ntypes;
85   int ntypes2 = ntypes*ntypes;
86 
87   fast_alpha_t* _noalias fast_alpha =
88     (fast_alpha_t*) malloc(ntypes2*sizeof(fast_alpha_t));
89   for (i = 0; i < ntypes; i++) for (j = 0; j < ntypes; j++) {
90     fast_alpha_t& a = fast_alpha[i*ntypes+j];
91     a.cutsq = cutsq[i+1][j+1];
92     a.uf1 = uf1[i+1][j+1];
93     a.uf2 = uf2[i+1][j+1];
94     a.uf3 = uf3[i+1][j+1];
95     a.scale = scale[i+1][j+1];
96     a.offset = offset[i+1][j+1];
97   }
98   fast_alpha_t* _noalias tabsix = fast_alpha;
99 
100   // loop over neighbors of my atoms
101 
102   for (ii = 0; ii < inum; ii++) {
103     i = ilist[ii];
104     double xtmp = xx[i].x;
105     double ytmp = xx[i].y;
106     double ztmp = xx[i].z;
107     itype = type[i] - 1;
108     int* _noalias jlist = firstneigh[i];
109     jnum = numneigh[i];
110 
111     double tmpfx = 0.0;
112     double tmpfy = 0.0;
113     double tmpfz = 0.0;
114 
115     fast_alpha_t* _noalias tabsixi = (fast_alpha_t*)&tabsix[itype*ntypes];
116 
117     for (jj = 0; jj < jnum; jj++) {
118       j = jlist[jj];
119       sbindex = sbmask(j);
120 
121       if (sbindex == 0) {
122         double delx = xtmp - xx[j].x;
123         double dely = ytmp - xx[j].y;
124         double delz = ztmp - xx[j].z;
125         double rsq = delx*delx + dely*dely + delz*delz;
126 
127         jtype = type[j] - 1;
128 
129         fast_alpha_t& a = tabsixi[jtype];
130 
131         if (rsq < a.cutsq) {
132           double expuf = exp(- rsq * a.uf2);
133           double fpair = a.scale * a.uf1 * expuf / (1.0 - expuf);
134 
135           tmpfx += delx*fpair;
136           tmpfy += dely*fpair;
137           tmpfz += delz*fpair;
138           if (NEWTON_PAIR || j < nlocal) {
139             ff[j].x -= delx*fpair;
140             ff[j].y -= dely*fpair;
141             ff[j].z -= delz*fpair;
142           }
143 
144           if (EFLAG) evdwl = - a.uf3 * log(1.0 - expuf) - a.offset;
145 
146           if (EVFLAG)
147             ev_tally(i,j,nlocal,NEWTON_PAIR,
148                      evdwl,0.0,fpair,delx,dely,delz);
149         }
150 
151       } else {
152         factor_lj = special_lj[sbindex];
153         j &= NEIGHMASK;
154 
155         double delx = xtmp - xx[j].x;
156         double dely = ytmp - xx[j].y;
157         double delz = ztmp - xx[j].z;
158         double rsq = delx*delx + dely*dely + delz*delz;
159 
160         int jtype1 = type[j];
161         jtype = jtype1 - 1;
162 
163         fast_alpha_t& a = tabsixi[jtype];
164         if (rsq < a.cutsq) {
165           fast_alpha_t& a = tabsixi[jtype];
166           double expuf = exp(- rsq * a.uf2);
167           double fpair = a.scale * factor_lj * a.uf1 * expuf / (1.0 - expuf);
168 
169           tmpfx += delx*fpair;
170           tmpfy += dely*fpair;
171           tmpfz += delz*fpair;
172           if (NEWTON_PAIR || j < nlocal) {
173             ff[j].x -= delx*fpair;
174             ff[j].y -= dely*fpair;
175             ff[j].z -= delz*fpair;
176           }
177 
178           if (EFLAG) {
179             evdwl = - a.uf3 * log(1.0 - expuf) - a.offset;
180             evdwl *= factor_lj;
181           }
182 
183           if (EVFLAG) ev_tally(i,j,nlocal,NEWTON_PAIR,
184                                evdwl,0.0,fpair,delx,dely,delz);
185         }
186       }
187     }
188 
189     ff[i].x += tmpfx;
190     ff[i].y += tmpfy;
191     ff[i].z += tmpfz;
192   }
193 
194   free(fast_alpha); fast_alpha = 0;
195 
196   if (vflag_fdotr) virial_fdotr_compute();
197 }
198