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