Tests of restrained listed potentials.
[alexxy/gromacs.git] / src / gromacs / nbnxm / internal.h
1 /*
2  * This file is part of the GROMACS molecular simulation package.
3  *
4  * Copyright (c) 2012,2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
5  * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
6  * and including many others, as listed in the AUTHORS file in the
7  * top-level source directory and at http://www.gromacs.org.
8  *
9  * GROMACS is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public License
11  * as published by the Free Software Foundation; either version 2.1
12  * of the License, or (at your option) any later version.
13  *
14  * GROMACS is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with GROMACS; if not, see
21  * http://www.gnu.org/licenses, or write to the Free Software Foundation,
22  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA.
23  *
24  * If you want to redistribute modifications to GROMACS, please
25  * consider that scientific software is very special. Version
26  * control is crucial - bugs must be traceable. We will be happy to
27  * consider code for inclusion in the official distribution, but
28  * derived work must not be called official GROMACS. Details are found
29  * in the README & COPYING files - if they are missing, get the
30  * official version at http://www.gromacs.org.
31  *
32  * To help us fund GROMACS development, we humbly ask that you cite
33  * the research papers on the package. Check out http://www.gromacs.org.
34  */
35
36 /*! \internal \file
37  *
38  * \brief Declares internal nbnxm module details
39  *
40  * \author Berk Hess <hess@kth.se>
41  *
42  * \ingroup module_nbnxm
43  */
44
45 #ifndef GMX_NBNXM_INTERNAL_H
46 #define GMX_NBNXM_INTERNAL_H
47
48 #include <memory>
49 #include <vector>
50
51 #include "gromacs/domdec/domdec.h"
52 #include "gromacs/math/vectypes.h"
53 #include "gromacs/nbnxm/pairlist.h"
54 #include "gromacs/simd/simd.h"
55 #include "gromacs/timing/cyclecounter.h"
56 #include "gromacs/utility/alignedallocator.h"
57 #include "gromacs/utility/arrayref.h"
58 #include "gromacs/utility/real.h"
59
60 struct gmx_domdec_zones_t;
61
62
63 // TODO Document after refactoring
64 #ifndef DOXYGEN
65
66 /* Strides for x/f with xyz and xyzq coordinate (and charge) storage */
67 #define STRIDE_XYZ         3
68 #define STRIDE_XYZQ        4
69 /* Size of packs of x, y or z with SIMD packed coords/forces */
70 static const int c_packX4 = 4;
71 static const int c_packX8 = 8;
72 /* Strides for a pack of 4 and 8 coordinates/forces */
73 #define STRIDE_P4         (DIM*c_packX4)
74 #define STRIDE_P8         (DIM*c_packX8)
75
76 /* Returns the index in a coordinate array corresponding to atom a */
77 template<int packSize> static inline int atom_to_x_index(int a)
78 {
79     return DIM*(a & ~(packSize - 1)) + (a & (packSize - 1));
80 }
81
82
83 #if GMX_SIMD
84 /* Memory alignment in bytes as required by SIMD aligned loads/stores */
85 #define NBNXN_MEM_ALIGN  (GMX_SIMD_REAL_WIDTH*sizeof(real))
86 #else
87 /* No alignment required, but set it so we can call the same routines */
88 #define NBNXN_MEM_ALIGN  32
89 #endif
90
91
92 /* Bounding box calculations are (currently) always in single precision, so
93  * we only need to check for single precision support here.
94  * This uses less (cache-)memory and SIMD is faster, at least on x86.
95  */
96 #if GMX_SIMD4_HAVE_FLOAT
97 #    define NBNXN_SEARCH_BB_SIMD4      1
98 /* Memory alignment in bytes as required by SIMD aligned loads/stores */
99 #    define NBNXN_SEARCH_BB_MEM_ALIGN  (GMX_SIMD4_WIDTH*sizeof(float))
100 #else
101 #    define NBNXN_SEARCH_BB_SIMD4      0
102 /* No alignment required, but set it so we can call the same routines */
103 #    define NBNXN_SEARCH_BB_MEM_ALIGN  32
104 #endif
105
106
107 /* Pair search box lower and upper corner in x,y,z.
108  * Store this in 4 iso 3 reals, which is useful with 4-wide SIMD.
109  * To avoid complicating the code we also use 4 without 4-wide SIMD.
110  */
111 #define NNBSBB_C         4
112 /* Pair search box lower and upper bound in z only. */
113 #define NNBSBB_D         2
114 /* Pair search box lower and upper corner x,y,z indices, entry 3 is unused */
115 #define BB_X  0
116 #define BB_Y  1
117 #define BB_Z  2
118
119
120 #if NBNXN_SEARCH_BB_SIMD4
121 /* Always use 4-wide SIMD for bounding box calculations */
122
123 #    if !GMX_DOUBLE
124 /* Single precision BBs + coordinates, we can also load coordinates with SIMD */
125 #        define NBNXN_SEARCH_SIMD4_FLOAT_X_BB  1
126 #    else
127 #        define NBNXN_SEARCH_SIMD4_FLOAT_X_BB  0
128 #    endif
129
130 /* The packed bounding box coordinate stride is always set to 4.
131  * With AVX we could use 8, but that turns out not to be faster.
132  */
133 #    define STRIDE_PBB       GMX_SIMD4_WIDTH
134 #    define STRIDE_PBB_2LOG  2
135
136 /* Store bounding boxes corners as quadruplets: xxxxyyyyzzzz */
137 #    define NBNXN_BBXXXX  1
138 /* Size of bounding box corners quadruplet */
139 #    define NNBSBB_XXXX  (NNBSBB_D*DIM*STRIDE_PBB)
140
141 #else  /* NBNXN_SEARCH_BB_SIMD4 */
142
143 #    define NBNXN_SEARCH_SIMD4_FLOAT_X_BB  0
144 #    define NBNXN_BBXXXX                   0
145
146 #endif /* NBNXN_SEARCH_BB_SIMD4 */
147
148 #endif // !DOXYGEN
149
150
151 /*! \brief Convenience declaration for an std::vector with aligned memory */
152 template <class T>
153 using AlignedVector = std::vector < T, gmx::AlignedAllocator < T>>;
154
155
156 /* Bounding box for a nbnxn atom cluster */
157 typedef struct {
158     float lower[NNBSBB_C];
159     float upper[NNBSBB_C];
160 } nbnxn_bb_t;
161
162
163 /* A pair-search grid struct for one domain decomposition zone
164  *
165  * Note that when atom groups, instead of individual atoms, are assigned
166  * to grid cells, individual atoms can be geometrically outside the cell
167  * and grid that they have been assigned to (as determined by the center
168  * or geometry of the atom group they belong to).
169  */
170 struct nbnxn_grid_t
171 {
172     rvec     c0;                   /* The lower corner of the (local) grid        */
173     rvec     c1;                   /* The upper corner of the (local) grid        */
174     rvec     size;                 /* c1 - c0                                     */
175     real     atom_density;         /* The atom number density for the local grid  */
176     real     maxAtomGroupRadius;   /* The maximum distance an atom can be outside
177                                     * of a cell and outside of the grid
178                                     */
179
180     gmx_bool bSimple;              /* Is this grid simple or super/sub            */
181     int      na_c;                 /* Number of atoms per cluster                 */
182     int      na_cj;                /* Number of atoms for list j-clusters         */
183     int      na_sc;                /* Number of atoms per super-cluster           */
184     int      na_c_2log;            /* 2log of na_c                                */
185
186     int      numCells[DIM - 1];    /* Number of cells along x/y                   */
187     int      nc;                   /* Total number of cells                       */
188
189     real     cellSize[DIM - 1];    /* size of a cell                              */
190     real     invCellSize[DIM - 1]; /* 1/cellSize                                  */
191
192     int      cell0;                /* Index in nbs->cell corresponding to cell 0  */
193
194     /* Grid data */
195     std::vector<int> cxy_na;        /* The number of atoms for each column in x,y  */
196     std::vector<int> cxy_ind;       /* Grid (super)cell index, offset from cell0   */
197
198     std::vector<int> nsubc;         /* The number of sub cells for each super cell */
199
200     /* Bounding boxes */
201     std::vector<float>                                    bbcz;                /* Bounding boxes in z for the cells */
202     std::vector < nbnxn_bb_t, gmx::AlignedAllocator < nbnxn_bb_t>> bb;         /* 3D bounding boxes for the sub cells */
203     std::vector < nbnxn_bb_t, gmx::AlignedAllocator < nbnxn_bb_t>> bbjStorage; /* 3D j-bounding boxes for the case where
204                                                                                 * the i- and j-cluster sizes are different */
205     gmx::ArrayRef<nbnxn_bb_t>                              bbj;                /* 3D j-bounding boxes */
206     std::vector < float, gmx::AlignedAllocator < float>>            pbb;       /* 3D b. boxes in xxxx format per super cell   */
207
208     /* Bit-flag information */
209     std::vector<int>          flags;     /* Flags for properties of clusters in each cell */
210     std::vector<unsigned int> fep;       /* FEP signal bits for atoms in each cluster */
211
212     /* Statistics */
213     int                       nsubc_tot; /* Total number of subcell, used for printing  */
214 };
215
216 /* Working data for the actual i-supercell during pair search */
217 struct NbnxnPairlistCpuWork
218 {
219     // Struct for storing coordinats and bounding box for an i-entry during search
220     struct IClusterData
221     {
222         IClusterData() :
223             bb(1),
224             x(c_nbnxnCpuIClusterSize*DIM),
225             xSimd(c_nbnxnCpuIClusterSize*DIM*GMX_REAL_MAX_SIMD_WIDTH)
226         {
227         }
228
229         // The bounding boxes, pbc shifted, for each cluster
230         AlignedVector<nbnxn_bb_t> bb;
231         // The coordinates, pbc shifted, for each atom
232         std::vector<real>         x;
233         // Aligned list for storing 4*DIM*GMX_SIMD_REAL_WIDTH reals
234         AlignedVector<real>       xSimd;
235     };
236
237     // Protect data from cache pollution between threads
238     gmx_cache_protect_t       cp0;
239
240     // Work data for generating an IEntry in the pairlist
241     IClusterData              iClusterData;
242     // The current cj_ind index for the current list
243     int                       cj_ind;
244     // Temporary j-cluster list, used for sorting on exclusions
245     std::vector<nbnxn_cj_t>   cj;
246
247     // Nr. of cluster pairs without Coulomb for flop counting
248     int                       ncj_noq;
249     // Nr. of cluster pairs with 1/2 LJ for flop count
250     int                       ncj_hlj;
251
252     // Protect data from cache pollution between threads
253     gmx_cache_protect_t       cp1;
254 };
255
256 /* Working data for the actual i-supercell during pair search */
257 struct NbnxnPairlistGpuWork
258 {
259     struct ISuperClusterData
260     {
261         ISuperClusterData() :
262             bb(c_gpuNumClusterPerCell),
263 #if NBNXN_SEARCH_BB_SIMD4
264             bbPacked(c_gpuNumClusterPerCell/STRIDE_PBB*NNBSBB_XXXX),
265 #endif
266             x(c_gpuNumClusterPerCell*c_nbnxnGpuClusterSize*DIM),
267             xSimd(c_gpuNumClusterPerCell*c_nbnxnGpuClusterSize*DIM)
268         {
269         }
270
271         // The bounding boxes, pbc shifted, for each cluster
272         AlignedVector<nbnxn_bb_t> bb;
273         // As bb, but in packed xxxx format
274         AlignedVector<float>      bbPacked;
275         // The coordinates, pbc shifted, for each atom
276         AlignedVector<real>       x;
277         // Aligned coordinate list used for 4*DIM*GMX_SIMD_REAL_WIDTH floats
278         AlignedVector<real>       xSimd;
279     };
280
281     NbnxnPairlistGpuWork() :
282         distanceBuffer(c_gpuNumClusterPerCell),
283         sci_sort({}, {gmx::PinningPolicy::PinnedIfSupported})
284     {
285     }
286
287     // Protect data from cache pollution between threads
288     gmx_cache_protect_t       cp0;
289
290     // Work data for generating an i-entry in the pairlist
291     ISuperClusterData         iSuperClusterData;
292     // The current j-cluster index for the current list
293     int                       cj_ind;
294     // Bounding box distance work array
295     AlignedVector<float>      distanceBuffer;
296
297     // Buffer for sorting list entries
298     std::vector<int>          sortBuffer;
299
300     // Second sci array, for sorting
301     gmx::HostVector<nbnxn_sci_t> sci_sort;
302
303     // Protect data from cache pollution between threads
304     gmx_cache_protect_t       cp1;
305 };
306
307 /* Local cycle count struct for profiling */
308 typedef struct {
309     int          count;
310     gmx_cycles_t c;
311     gmx_cycles_t start;
312 } nbnxn_cycle_t;
313
314 /* Local cycle count enum for profiling */
315 enum {
316     enbsCCgrid, enbsCCsearch, enbsCCcombine, enbsCCreducef, enbsCCnr
317 };
318
319 /* Thread-local work struct, contains part of nbnxn_grid_t */
320 struct nbnxn_search_work_t
321 {
322     nbnxn_search_work_t();
323
324     ~nbnxn_search_work_t();
325
326     gmx_cache_protect_t       cp0;          /* Buffer to avoid cache polution */
327
328     std::vector<int>          cxy_na;       /* Grid column atom counts temporary buffer */
329
330     std::vector<int>          sortBuffer;   /* Temporary buffer for sorting atoms within a grid column */
331
332     nbnxn_buffer_flags_t      buffer_flags; /* Flags for force buffer access */
333
334     int                       ndistc;       /* Number of distance checks for flop counting */
335
336
337     std::unique_ptr<t_nblist> nbl_fep;      /* Temporary FEP list for load balancing */
338
339     nbnxn_cycle_t             cc[enbsCCnr]; /* Counters for thread-local cycles */
340
341     gmx_cache_protect_t       cp1;          /* Buffer to avoid cache polution */
342 };
343
344 /* Main pair-search struct, contains the grid(s), not the pair-list(s) */
345 struct nbnxn_search
346 {
347     /* \brief Constructor
348      *
349      * \param[in] n_dd_cells   The number of domain decomposition cells per dimension, without DD nullptr should be passed
350      * \param[in] zones        The domain decomposition zone setup, without DD nullptr should be passed
351      * \param[in] bFEP         Tells whether non-bonded interactions are perturbed
352      * \param[in] nthread_max  The maximum number of threads used in the search
353      */
354
355     nbnxn_search(const ivec               *n_dd_cells,
356                  const gmx_domdec_zones_t *zones,
357                  gmx_bool                  bFEP,
358                  int                       nthread_max);
359
360     gmx_bool                   bFEP;            /* Do we have perturbed atoms? */
361     int                        ePBC;            /* PBC type enum                              */
362     matrix                     box;             /* The periodic unit-cell                     */
363
364     gmx_bool                   DomDec;          /* Are we doing domain decomposition?         */
365     ivec                       dd_dim;          /* Are we doing DD in x,y,z?                  */
366     const gmx_domdec_zones_t  *zones;           /* The domain decomposition zones        */
367
368     std::vector<nbnxn_grid_t>  grid;            /* Array of grids, size ngrid                 */
369     std::vector<int>           cell;            /* Actual allocated cell array for all grids  */
370     std::vector<int>           a;               /* Atom index for grid, the inverse of cell   */
371
372     int                        natoms_local;    /* The local atoms run from 0 to natoms_local */
373     int                        natoms_nonlocal; /* The non-local atoms run from natoms_local
374                                                  * to natoms_nonlocal */
375
376     gmx_bool             print_cycles;
377     int                  search_count;
378     nbnxn_cycle_t        cc[enbsCCnr];
379
380     /* Thread-local work data */
381     mutable std::vector<nbnxn_search_work_t> work; /* Work array, one entry for each thread */
382 };
383
384
385 /*! \brief Start an nbnxn cycle counter */
386 static inline void nbs_cycle_start(nbnxn_cycle_t *cc)
387 {
388     cc->start = gmx_cycles_read();
389 }
390
391 /*! \brief Stop an nbnxn cycle counter */
392 static inline void nbs_cycle_stop(nbnxn_cycle_t *cc)
393 {
394     cc->c += gmx_cycles_read() - cc->start;
395     cc->count++;
396 }
397
398 #endif