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: Ray Shan (SNL)
17 ------------------------------------------------------------------------- */
18 
19 #include "pair_lj_class2_kokkos.h"
20 #include <cmath>
21 #include <cstring>
22 #include "kokkos.h"
23 #include "atom_kokkos.h"
24 #include "force.h"
25 #include "neighbor.h"
26 #include "neigh_list.h"
27 #include "neigh_request.h"
28 #include "update.h"
29 #include "respa.h"
30 #include "memory_kokkos.h"
31 #include "error.h"
32 #include "atom_masks.h"
33 
34 using namespace LAMMPS_NS;
35 
36 #define KOKKOS_CUDA_MAX_THREADS 256
37 #define KOKKOS_CUDA_MIN_BLOCKS 8
38 
39 /* ---------------------------------------------------------------------- */
40 
41 template<class DeviceType>
PairLJClass2Kokkos(LAMMPS * lmp)42 PairLJClass2Kokkos<DeviceType>::PairLJClass2Kokkos(LAMMPS *lmp) : PairLJClass2(lmp)
43 {
44   respa_enable = 0;
45 
46   kokkosable = 1;
47   atomKK = (AtomKokkos *) atom;
48   execution_space = ExecutionSpaceFromDevice<DeviceType>::space;
49   datamask_read = X_MASK | F_MASK | TYPE_MASK | ENERGY_MASK | VIRIAL_MASK;
50   datamask_modify = F_MASK | ENERGY_MASK | VIRIAL_MASK;
51 }
52 
53 /* ---------------------------------------------------------------------- */
54 
55 template<class DeviceType>
~PairLJClass2Kokkos()56 PairLJClass2Kokkos<DeviceType>::~PairLJClass2Kokkos()
57 {
58   if (copymode) return;
59 
60   if (allocated) {
61     memoryKK->destroy_kokkos(k_eatom,eatom);
62     memoryKK->destroy_kokkos(k_vatom,vatom);
63     memoryKK->destroy_kokkos(k_cutsq,cutsq);
64   }
65 }
66 
67 /* ---------------------------------------------------------------------- */
68 
69 template<class DeviceType>
compute(int eflag_in,int vflag_in)70 void PairLJClass2Kokkos<DeviceType>::compute(int eflag_in, int vflag_in)
71 {
72   eflag = eflag_in;
73   vflag = vflag_in;
74 
75 
76   if (neighflag == FULL) no_virial_fdotr_compute = 1;
77 
78   ev_init(eflag,vflag,0);
79 
80   // reallocate per-atom arrays if necessary
81 
82   if (eflag_atom) {
83     memoryKK->destroy_kokkos(k_eatom,eatom);
84     memoryKK->create_kokkos(k_eatom,eatom,maxeatom,"pair:eatom");
85     d_eatom = k_eatom.view<DeviceType>();
86   }
87   if (vflag_atom) {
88     memoryKK->destroy_kokkos(k_vatom,vatom);
89     memoryKK->create_kokkos(k_vatom,vatom,maxvatom,"pair:vatom");
90     d_vatom = k_vatom.view<DeviceType>();
91   }
92 
93   atomKK->sync(execution_space,datamask_read);
94   k_cutsq.template sync<DeviceType>();
95   k_params.template sync<DeviceType>();
96   if (eflag || vflag) atomKK->modified(execution_space,datamask_modify);
97   else atomKK->modified(execution_space,F_MASK);
98 
99   x = atomKK->k_x.view<DeviceType>();
100   c_x = atomKK->k_x.view<DeviceType>();
101   f = atomKK->k_f.view<DeviceType>();
102   type = atomKK->k_type.view<DeviceType>();
103   tag = atomKK->k_tag.view<DeviceType>();
104   nlocal = atom->nlocal;
105   nall = atom->nlocal + atom->nghost;
106   newton_pair = force->newton_pair;
107   special_lj[0] = force->special_lj[0];
108   special_lj[1] = force->special_lj[1];
109   special_lj[2] = force->special_lj[2];
110   special_lj[3] = force->special_lj[3];
111 
112   // loop over neighbors of my atoms
113 
114   EV_FLOAT ev = pair_compute<PairLJClass2Kokkos<DeviceType>,void >(this,(NeighListKokkos<DeviceType>*)list);
115 
116   if (eflag) eng_vdwl += ev.evdwl;
117   if (vflag_global) {
118     virial[0] += ev.v[0];
119     virial[1] += ev.v[1];
120     virial[2] += ev.v[2];
121     virial[3] += ev.v[3];
122     virial[4] += ev.v[4];
123     virial[5] += ev.v[5];
124   }
125 
126   if (eflag_atom) {
127     k_eatom.template modify<DeviceType>();
128     k_eatom.template sync<LMPHostType>();
129   }
130 
131   if (vflag_atom) {
132     k_vatom.template modify<DeviceType>();
133     k_vatom.template sync<LMPHostType>();
134   }
135 
136   if (vflag_fdotr) pair_virial_fdotr_compute(this);
137 
138 }
139 
140 template<class DeviceType>
141 template<bool STACKPARAMS, class Specialisation>
142 KOKKOS_INLINE_FUNCTION
143 F_FLOAT PairLJClass2Kokkos<DeviceType>::
compute_fpair(const F_FLOAT & rsq,const int & i,const int & j,const int & itype,const int & jtype) const144 compute_fpair(const F_FLOAT& rsq, const int& i, const int&j, const int& itype, const int& jtype) const {
145   (void) i;
146   (void) j;
147   const F_FLOAT r2inv = 1.0/rsq;
148   const F_FLOAT rinv = sqrt(r2inv);
149   const F_FLOAT r3inv = r2inv*rinv;
150   const F_FLOAT r6inv = r3inv*r3inv;
151 
152   const F_FLOAT forcelj = r6inv *
153     ((STACKPARAMS?m_params[itype][jtype].lj1:params(itype,jtype).lj1)*r3inv -
154      (STACKPARAMS?m_params[itype][jtype].lj2:params(itype,jtype).lj2));
155 
156   return forcelj*r2inv;
157 
158 }
159 
160 template<class DeviceType>
161 template<bool STACKPARAMS, class Specialisation>
162 KOKKOS_INLINE_FUNCTION
163 F_FLOAT PairLJClass2Kokkos<DeviceType>::
compute_evdwl(const F_FLOAT & rsq,const int & i,const int & j,const int & itype,const int & jtype) const164 compute_evdwl(const F_FLOAT& rsq, const int& i, const int&j, const int& itype, const int& jtype) const {
165   (void) i;
166   (void) j;
167   const F_FLOAT r2inv = 1.0/rsq;
168   const F_FLOAT rinv = sqrt(r2inv);
169   const F_FLOAT r3inv = r2inv*rinv;
170   const F_FLOAT r6inv = r3inv*r3inv;
171 
172   return r6inv*((STACKPARAMS?m_params[itype][jtype].lj3:params(itype,jtype).lj3)*r3inv -
173                 (STACKPARAMS?m_params[itype][jtype].lj4:params(itype,jtype).lj4)) -
174                 (STACKPARAMS?m_params[itype][jtype].offset:params(itype,jtype).offset);
175 }
176 
177 /* ----------------------------------------------------------------------
178    allocate all arrays
179 ------------------------------------------------------------------------- */
180 
181 template<class DeviceType>
allocate()182 void PairLJClass2Kokkos<DeviceType>::allocate()
183 {
184   PairLJClass2::allocate();
185 
186   int n = atom->ntypes;
187   memory->destroy(cutsq);
188   memoryKK->create_kokkos(k_cutsq,cutsq,n+1,n+1,"pair:cutsq");
189   d_cutsq = k_cutsq.template view<DeviceType>();
190   k_params = Kokkos::DualView<params_lj**,Kokkos::LayoutRight,DeviceType>("PairLJClass2::params",n+1,n+1);
191   params = k_params.template view<DeviceType>();
192 }
193 
194 /* ----------------------------------------------------------------------
195    global settings
196 ------------------------------------------------------------------------- */
197 
198 template<class DeviceType>
settings(int narg,char ** arg)199 void PairLJClass2Kokkos<DeviceType>::settings(int narg, char **arg)
200 {
201   if (narg > 2) error->all(FLERR,"Illegal pair_style command");
202 
203   PairLJClass2::settings(1,arg);
204 }
205 
206 /* ----------------------------------------------------------------------
207    init specific to this pair style
208 ------------------------------------------------------------------------- */
209 
210 template<class DeviceType>
init_style()211 void PairLJClass2Kokkos<DeviceType>::init_style()
212 {
213   PairLJClass2::init_style();
214 
215   // error if rRESPA with inner levels
216 
217   if (update->whichflag == 1 && utils::strmatch(update->integrate_style,"^respa")) {
218     int respa = 0;
219     if (((Respa *) update->integrate)->level_inner >= 0) respa = 1;
220     if (((Respa *) update->integrate)->level_middle >= 0) respa = 2;
221     if (respa)
222       error->all(FLERR,"Cannot use Kokkos pair style with rRESPA inner/middle");
223   }
224 
225   // irequest = neigh request made by parent class
226 
227   neighflag = lmp->kokkos->neighflag;
228   int irequest = neighbor->nrequest - 1;
229 
230   neighbor->requests[irequest]->
231     kokkos_host = std::is_same<DeviceType,LMPHostType>::value &&
232     !std::is_same<DeviceType,LMPDeviceType>::value;
233   neighbor->requests[irequest]->
234     kokkos_device = std::is_same<DeviceType,LMPDeviceType>::value;
235 
236   if (neighflag == FULL) {
237     neighbor->requests[irequest]->full = 1;
238     neighbor->requests[irequest]->half = 0;
239   } else if (neighflag == HALF || neighflag == HALFTHREAD) {
240     neighbor->requests[irequest]->full = 0;
241     neighbor->requests[irequest]->half = 1;
242   } else {
243     error->all(FLERR,"Cannot use chosen neighbor list style with lj/class2/kk");
244   }
245 }
246 
247 /* ----------------------------------------------------------------------
248    init for one type pair i,j and corresponding j,i
249 ------------------------------------------------------------------------- */
250 
251 template<class DeviceType>
init_one(int i,int j)252 double PairLJClass2Kokkos<DeviceType>::init_one(int i, int j)
253 {
254   double cutone = PairLJClass2::init_one(i,j);
255 
256   k_params.h_view(i,j).lj1 = lj1[i][j];
257   k_params.h_view(i,j).lj2 = lj2[i][j];
258   k_params.h_view(i,j).lj3 = lj3[i][j];
259   k_params.h_view(i,j).lj4 = lj4[i][j];
260   k_params.h_view(i,j).offset = offset[i][j];
261   k_params.h_view(i,j).cutsq = cutone*cutone;
262   k_params.h_view(j,i) = k_params.h_view(i,j);
263   if (i<MAX_TYPES_STACKPARAMS+1 && j<MAX_TYPES_STACKPARAMS+1) {
264     m_params[i][j] = m_params[j][i] = k_params.h_view(i,j);
265     m_cutsq[j][i] = m_cutsq[i][j] = cutone*cutone;
266   }
267   k_cutsq.h_view(i,j) = k_cutsq.h_view(j,i) = cutone*cutone;
268   k_cutsq.template modify<LMPHostType>();
269   k_params.template modify<LMPHostType>();
270 
271   return cutone;
272 }
273 
274 
275 namespace LAMMPS_NS {
276 template class PairLJClass2Kokkos<LMPDeviceType>;
277 #ifdef LMP_KOKKOS_GPU
278 template class PairLJClass2Kokkos<LMPHostType>;
279 #endif
280 }
281 
282