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: Trung Dac Nguyen (ndactrung@gmail.com)
17 ------------------------------------------------------------------------- */
18 
19 #include "pair_tersoff_mod_gpu.h"
20 
21 #include "atom.h"
22 #include "comm.h"
23 #include "domain.h"
24 #include "error.h"
25 #include "force.h"
26 #include "gpu_extra.h"
27 #include "memory.h"
28 #include "neigh_list.h"
29 #include "neigh_request.h"
30 #include "neighbor.h"
31 #include "suffix.h"
32 
33 using namespace LAMMPS_NS;
34 
35 // External functions from cuda library for atom decomposition
36 
37 int tersoff_mod_gpu_init(const int ntypes, const int inum, const int nall,
38   const int max_nbors, const double cell_size, int &gpu_mode, FILE *screen,
39   int* host_map, const int nelements, int*** host_elem3param, const int nparams,
40   const double* ts_lam1, const double* ts_lam2, const double* ts_lam3,
41   const double* ts_powermint, const double* ts_biga, const double* ts_bigb,
42   const double* ts_bigr, const double* ts_bigd, const double* ts_c1,
43   const double* ts_c2, const double* ts_c3, const double* ts_c4,
44   const double* ts_c5, const double* ts_h, const double* ts_beta,
45   const double* ts_powern, const double* ts_powern_del,
46   const double* ts_ca1, const double* ts_cutsq);
47 void tersoff_mod_gpu_clear();
48 int ** tersoff_mod_gpu_compute_n(const int ago, const int inum_full,
49                     const int nall, double **host_x, int *host_type,
50                     double *sublo, double *subhi, tagint *tag, int **nspecial,
51                     tagint **special, const bool eflag, const bool vflag,
52                     const bool eatom, const bool vatom, int &host_start,
53                     int **ilist, int **jnum, const double cpu_time,
54                     bool &success);
55 void tersoff_mod_gpu_compute(const int ago, const int nlocal, const int nall,
56                     const int nlist, double **host_x, int *host_type,
57                     int *ilist, int *numj, int **firstneigh, const bool eflag,
58                     const bool vflag, const bool eatom, const bool vatom,
59                     int &host_start, const double cpu_time, bool &success);
60 double tersoff_mod_gpu_bytes();
61 
62 /* ---------------------------------------------------------------------- */
63 
PairTersoffMODGPU(LAMMPS * lmp)64 PairTersoffMODGPU::PairTersoffMODGPU(LAMMPS *lmp) : PairTersoffMOD(lmp),
65   gpu_mode(GPU_FORCE)
66 {
67   cpu_time = 0.0;
68   suffix_flag |= Suffix::GPU;
69   GPU_EXTRA::gpu_ready(lmp->modify, lmp->error);
70 
71   cutghost = nullptr;
72   ghostneigh = 1;
73 }
74 
75 /* ----------------------------------------------------------------------
76    check if allocated, since class can be destructed when incomplete
77 ------------------------------------------------------------------------- */
78 
~PairTersoffMODGPU()79 PairTersoffMODGPU::~PairTersoffMODGPU()
80 {
81   tersoff_mod_gpu_clear();
82   if (allocated)
83     memory->destroy(cutghost);
84 }
85 
86 /* ---------------------------------------------------------------------- */
87 
compute(int eflag,int vflag)88 void PairTersoffMODGPU::compute(int eflag, int vflag)
89 {
90   ev_init(eflag,vflag);
91 
92   int nall = atom->nlocal + atom->nghost;
93   int inum, host_start;
94 
95   bool success = true;
96   int *ilist, *numneigh, **firstneigh;
97   if (gpu_mode != GPU_FORCE) {
98     double sublo[3],subhi[3];
99     if (domain->triclinic == 0) {
100       sublo[0] = domain->sublo[0];
101       sublo[1] = domain->sublo[1];
102       sublo[2] = domain->sublo[2];
103       subhi[0] = domain->subhi[0];
104       subhi[1] = domain->subhi[1];
105       subhi[2] = domain->subhi[2];
106     } else {
107       domain->bbox(domain->sublo_lamda,domain->subhi_lamda,sublo,subhi);
108     }
109     inum = atom->nlocal;
110     firstneigh = tersoff_mod_gpu_compute_n(neighbor->ago, inum, nall,
111                                   atom->x, atom->type, sublo,
112                                   subhi, atom->tag, atom->nspecial,
113                                   atom->special, eflag, vflag, eflag_atom,
114                                   vflag_atom, host_start,
115                                   &ilist, &numneigh, cpu_time, success);
116   } else {
117     inum = list->inum;
118     ilist = list->ilist;
119     numneigh = list->numneigh;
120     firstneigh = list->firstneigh;
121 
122     tersoff_mod_gpu_compute(neighbor->ago, inum, nall, inum+list->gnum,
123                    atom->x, atom->type, ilist, numneigh, firstneigh, eflag,
124                    vflag, eflag_atom, vflag_atom, host_start, cpu_time,
125                    success);
126   }
127   if (!success)
128     error->one(FLERR,"Insufficient memory on accelerator");
129 }
130 
131 /* ---------------------------------------------------------------------- */
132 
allocate()133 void PairTersoffMODGPU::allocate()
134 {
135   PairTersoffMOD::allocate();
136   int n = atom->ntypes;
137 
138   memory->create(cutghost,n+1,n+1,"pair:cutghost");
139 }
140 
141 /* ----------------------------------------------------------------------
142    init specific to this pair style
143 ------------------------------------------------------------------------- */
144 
init_style()145 void PairTersoffMODGPU::init_style()
146 {
147   double cell_size = cutmax + neighbor->skin;
148 
149   if (atom->tag_enable == 0)
150     error->all(FLERR,"Pair style tersoff/mod/gpu requires atom IDs");
151   if (force->newton_pair != 0)
152     error->all(FLERR,"Pair style tersoff/mod/gpu requires newton pair off");
153 
154   double *lam1, *lam2, *lam3, *powermint;
155   double *biga, *bigb, *bigr, *bigd;
156   double *c1, *c2, *c3, *c4, *c5, *h;
157   double *beta, *powern, *ca1, *powern_del, *_cutsq;
158   lam1 = lam2 = lam3 = powermint = nullptr;
159   biga = bigb = bigr = bigd = nullptr;
160   powern_del = ca1 = nullptr;
161   c1 = c2 = c3 = c4 = c5 = h = nullptr;
162   beta = powern = _cutsq = nullptr;
163 
164   memory->create(lam1,nparams,"pair:lam1");
165   memory->create(lam2,nparams,"pair:lam2");
166   memory->create(lam3,nparams,"pair:lam3");
167   memory->create(powermint,nparams,"pair:powermint");
168   memory->create(biga,nparams,"pair:biga");
169   memory->create(bigb,nparams,"pair:bigb");
170   memory->create(bigr,nparams,"pair:bigr");
171   memory->create(bigd,nparams,"pair:bigd");
172   memory->create(c1,nparams,"pair:c1");
173   memory->create(c2,nparams,"pair:c2");
174   memory->create(c3,nparams,"pair:c3");
175   memory->create(c4,nparams,"pair:c4");
176   memory->create(c5,nparams,"pair:c5");
177   memory->create(h,nparams,"pair:h");
178   memory->create(beta,nparams,"pair:beta");
179   memory->create(powern,nparams,"pair:powern");
180   memory->create(powern_del,nparams,"pair:powern_del");
181   memory->create(ca1,nparams,"pair:ca1");
182   memory->create(_cutsq,nparams,"pair:_cutsq");
183 
184   for (int i = 0; i < nparams; i++) {
185     lam1[i] = params[i].lam1;
186     lam2[i] = params[i].lam2;
187     lam3[i] = params[i].lam3;
188     powermint[i] = params[i].powermint;
189     biga[i] = params[i].biga;
190     bigb[i] = params[i].bigb;
191     bigr[i] = params[i].bigr;
192     bigd[i] = params[i].bigd;
193     c1[i] = params[i].c1;
194     c2[i] = params[i].c2;
195     c3[i] = params[i].c3;
196     c4[i] = params[i].c4;
197     c5[i] = params[i].c5;
198     h[i] = params[i].h;
199     beta[i] = params[i].beta;
200     powern[i] = params[i].powern;
201     powern_del[i] = params[i].powern_del;
202     ca1[i] = params[i].ca1;
203     _cutsq[i] = params[i].cutsq;
204   }
205 
206   int mnf = 5e-2 * neighbor->oneatom;
207   int success = tersoff_mod_gpu_init(atom->ntypes+1, atom->nlocal,
208                                  atom->nlocal+atom->nghost, mnf,
209                                  cell_size, gpu_mode, screen, map, nelements,
210                                  elem3param, nparams, lam1, lam2, lam3,
211                                  powermint, biga, bigb, bigr, bigd,
212                                  c1, c2, c3, c4, c5, h, beta, powern,
213                                  powern_del, ca1, _cutsq);
214 
215   memory->destroy(lam1);
216   memory->destroy(lam2);
217   memory->destroy(lam3);
218   memory->destroy(powermint);
219   memory->destroy(biga);
220   memory->destroy(bigb);
221   memory->destroy(bigr);
222   memory->destroy(bigd);
223   memory->destroy(c1);
224   memory->destroy(c2);
225   memory->destroy(c3);
226   memory->destroy(c4);
227   memory->destroy(c5);
228   memory->destroy(h);
229   memory->destroy(beta);
230   memory->destroy(powern);
231   memory->destroy(ca1);
232   memory->destroy(powern_del);
233   memory->destroy(_cutsq);
234 
235   GPU_EXTRA::check_flag(success,error,world);
236 
237   if (gpu_mode == GPU_FORCE) {
238     int irequest = neighbor->request(this);
239     neighbor->requests[irequest]->half = 0;
240     neighbor->requests[irequest]->full = 1;
241     neighbor->requests[irequest]->ghost = 1;
242   }
243   if (comm->cutghostuser < (2.0*cutmax + neighbor->skin)) {
244     comm->cutghostuser = 2.0*cutmax + neighbor->skin;
245     if (comm->me == 0)
246        error->warning(FLERR,"Increasing communication cutoff for GPU style");
247   }
248 }
249 
250 /* ----------------------------------------------------------------------
251    init for one type pair i,j and corresponding j,i
252 ------------------------------------------------------------------------- */
253 
init_one(int i,int j)254 double PairTersoffMODGPU::init_one(int i, int j)
255 {
256   if (setflag[i][j] == 0) error->all(FLERR,"All pair coeffs are not set");
257   cutghost[i][j] = cutmax;
258   cutghost[j][i] = cutmax;
259 
260   return cutmax;
261 }
262 
263