Make nbnxm headers more self-contained
[alexxy/gromacs.git] / src / gromacs / nbnxm / atomdata.h
1 /*
2  * This file is part of the GROMACS molecular simulation package.
3  *
4  * Copyright (c) 2012,2013,2014,2015,2016 by the GROMACS development team.
5  * Copyright (c) 2017,2018,2019,2020, by the GROMACS development team, led by
6  * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
7  * and including many others, as listed in the AUTHORS file in the
8  * top-level source directory and at http://www.gromacs.org.
9  *
10  * GROMACS is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU Lesser General Public License
12  * as published by the Free Software Foundation; either version 2.1
13  * of the License, or (at your option) any later version.
14  *
15  * GROMACS is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18  * Lesser General Public License for more details.
19  *
20  * You should have received a copy of the GNU Lesser General Public
21  * License along with GROMACS; if not, see
22  * http://www.gnu.org/licenses, or write to the Free Software Foundation,
23  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA.
24  *
25  * If you want to redistribute modifications to GROMACS, please
26  * consider that scientific software is very special. Version
27  * control is crucial - bugs must be traceable. We will be happy to
28  * consider code for inclusion in the official distribution, but
29  * derived work must not be called official GROMACS. Details are found
30  * in the README & COPYING files - if they are missing, get the
31  * official version at http://www.gromacs.org.
32  *
33  * To help us fund GROMACS development, we humbly ask that you cite
34  * the research papers on the package. Check out http://www.gromacs.org.
35  */
36 /*! \libinternal \file
37  *  \brief
38  *  Functionality for per-atom data in the nbnxm module
39  *
40  *  \author Berk Hess <hess@kth.se>
41  *  \ingroup module_nbnxm
42  *  \inlibraryapi
43  */
44
45
46 #ifndef GMX_NBNXN_ATOMDATA_H
47 #define GMX_NBNXN_ATOMDATA_H
48
49 #include <cstdio>
50
51 #include "gromacs/gpu_utils/devicebuffer_datatype.h"
52 #include "gromacs/gpu_utils/hostallocator.h"
53 #include "gromacs/math/vectypes.h"
54 #include "gromacs/mdtypes/locality.h"
55 #include "gromacs/utility/basedefinitions.h"
56 #include "gromacs/utility/bitmask.h"
57 #include "gromacs/utility/real.h"
58
59 namespace gmx
60 {
61 class MDLogger;
62 }
63
64 struct gmx_nbnxm_gpu_t;
65 struct nbnxn_atomdata_t;
66 struct nonbonded_verlet_t;
67 struct t_mdatoms;
68 struct tMPI_Atomic;
69
70 class GpuEventSynchronizer;
71
72 namespace Nbnxm
73 {
74 class GridSet;
75 enum class KernelType;
76 } // namespace Nbnxm
77
78 //! Convenience type for vector with aligned memory
79 template<typename T>
80 using AlignedVector = std::vector<T, gmx::AlignedAllocator<T>>;
81
82 enum
83 {
84     nbatXYZ,
85     nbatXYZQ,
86     nbatX4,
87     nbatX8
88 };
89
90 //! Stride for coordinate/force arrays with xyz coordinate storage
91 static constexpr int STRIDE_XYZ = 3;
92 //! Stride for coordinate/force arrays with xyzq coordinate storage
93 static constexpr int STRIDE_XYZQ = 4;
94 //! Size of packs of x, y or z with SIMD 4-grouped packed coordinates/forces
95 static constexpr int c_packX4 = 4;
96 //! Size of packs of x, y or z with SIMD 8-grouped packed coordinates/forces
97 static constexpr int c_packX8 = 8;
98 //! Stridefor a pack of 4 coordinates/forces
99 static constexpr int STRIDE_P4 = DIM * c_packX4;
100 //! Stridefor a pack of 8 coordinates/forces
101 static constexpr int STRIDE_P8 = DIM * c_packX8;
102
103 //! Returns the index in a coordinate array corresponding to atom a
104 template<int packSize>
105 static inline int atom_to_x_index(int a)
106 {
107     return DIM * (a & ~(packSize - 1)) + (a & (packSize - 1));
108 }
109
110 // Struct that holds force and energy output buffers
111 struct nbnxn_atomdata_output_t
112 {
113     /* Constructor
114      *
115      * \param[in] kernelType              Type of non-bonded kernel
116      * \param[in] numEnergyGroups         The number of energy groups
117      * \param[in] simdEnergyBufferStride  Stride for entries in the energy buffers for SIMD kernels
118      * \param[in] pinningPolicy           Sets the pinning policy for all buffers used on the GPU
119      */
120     nbnxn_atomdata_output_t(Nbnxm::KernelType  kernelType,
121                             int                numEnergyGroups,
122                             int                simdEnergyBUfferStride,
123                             gmx::PinningPolicy pinningPolicy);
124
125     gmx::HostVector<real> f;      // f, size natoms*fstride
126     gmx::HostVector<real> fshift; // Shift force array, size SHIFTS*DIM
127     gmx::HostVector<real> Vvdw;   // Temporary Van der Waals group energy storage
128     gmx::HostVector<real> Vc;     // Temporary Coulomb group energy storage
129     AlignedVector<real>   VSvdw;  // Temporary SIMD Van der Waals group energy storage
130     AlignedVector<real>   VSc;    // Temporary SIMD Coulomb group energy storage
131 };
132
133 /*! \brief Block size in atoms for the non-bonded thread force-buffer reduction.
134  *
135  * Should be a multiple of all cell and x86 SIMD sizes (i.e. 2, 4 and 8).
136  * Should be small to reduce the reduction and zeroing cost,
137  * but too small will result in overhead.
138  * Currently the block size is NBNXN_BUFFERFLAG_SIZE*3*sizeof(real)=192 bytes.
139  */
140 #if GMX_DOUBLE
141 #    define NBNXN_BUFFERFLAG_SIZE 8
142 #else
143 #    define NBNXN_BUFFERFLAG_SIZE 16
144 #endif
145
146 /*! \brief We store the reduction flags as gmx_bitmask_t.
147  * This limits the number of flags to BITMASK_SIZE.
148  */
149 #define NBNXN_BUFFERFLAG_MAX_THREADS (BITMASK_SIZE)
150
151 /*! \internal
152  * \brief Flags for telling if threads write to force output buffers */
153 typedef struct
154 {
155     //! The number of flag blocks
156     int nflag;
157     //! Bit i is set when thread i writes to a cell-block
158     gmx_bitmask_t* flag;
159     //! Allocation size of cxy_flag
160     int flag_nalloc;
161 } nbnxn_buffer_flags_t;
162
163 /*! \brief LJ combination rules: geometric, Lorentz-Berthelot, none */
164 enum
165 {
166     ljcrGEOM,
167     ljcrLB,
168     ljcrNONE,
169     ljcrNR
170 };
171
172 /*! \internal
173  * \brief Struct that stores atom related data for the nbnxn module
174  *
175  * Note: performance would improve slightly when all std::vector containers
176  *       in this struct would not initialize during resize().
177  */
178 struct nbnxn_atomdata_t
179 { //NOLINT(clang-analyzer-optin.performance.Padding)
180     struct Params
181     {
182         /* Constructor
183          *
184          * \param[in] pinningPolicy  Sets the pinning policy for all data that might be transfered to a GPU
185          */
186         Params(gmx::PinningPolicy pinningPolicy);
187
188         // The number of different atom types
189         int numTypes;
190         // Lennard-Jone 6*C6 and 12*C12 parameters, size numTypes*2*2
191         gmx::HostVector<real> nbfp;
192         // Combination rule, see enum defined above
193         int comb_rule;
194         // LJ parameters per atom type, size numTypes*2
195         gmx::HostVector<real> nbfp_comb;
196         // As nbfp, but with a stride for the present SIMD architecture
197         AlignedVector<real> nbfp_aligned;
198         // Atom types per atom
199         gmx::HostVector<int> type;
200         // LJ parameters per atom for fast SIMD loading
201         gmx::HostVector<real> lj_comb;
202         // Charges per atom, not set with format nbatXYZQ
203         gmx::HostVector<real> q;
204         // The number of energy groups
205         int nenergrp;
206         // 2log(nenergrp)
207         int neg_2log;
208         // The energy groups, one int entry per cluster, only set when needed
209         gmx::HostVector<int> energrp;
210     };
211
212     /*! \internal
213      * \brief Diagonal and topology exclusion helper data for all SIMD kernels. */
214     struct SimdMasks
215     {
216         SimdMasks();
217
218         //! Helper data for setting up diagonal exclusion masks in the SIMD 4xN kernels
219         AlignedVector<real> diagonal_4xn_j_minus_i;
220         //! Helper data for setting up diaginal exclusion masks in the SIMD 2xNN kernels
221         AlignedVector<real> diagonal_2xnn_j_minus_i;
222         //! Filters for topology exclusion masks for the SIMD kernels
223         AlignedVector<uint32_t> exclusion_filter;
224         //! Filters for topology exclusion masks for double SIMD kernels without SIMD int32 logical support
225         AlignedVector<uint64_t> exclusion_filter64;
226         //! Array of masks needed for exclusions
227         AlignedVector<real> interaction_array;
228     };
229
230     /*! \brief Constructor
231      *
232      * \param[in] pinningPolicy  Sets the pinning policy for all data that might be transfered to a GPU
233      */
234     nbnxn_atomdata_t(gmx::PinningPolicy pinningPolicy);
235
236     //! Returns a const reference to the parameters
237     const Params& params() const { return params_; }
238
239     //! Returns a non-const reference to the parameters
240     Params& paramsDeprecated() { return params_; }
241
242     //! Returns the current total number of atoms stored
243     int numAtoms() const { return numAtoms_; }
244
245     //! Return the coordinate buffer, and q with xFormat==nbatXYZQ
246     gmx::ArrayRef<const real> x() const { return x_; }
247
248     //! Return the coordinate buffer, and q with xFormat==nbatXYZQ
249     gmx::ArrayRef<real> x() { return x_; }
250
251     //! Resizes the coordinate buffer and sets the number of atoms
252     void resizeCoordinateBuffer(int numAtoms);
253
254     //! Resizes the force buffers for the current number of atoms
255     void resizeForceBuffers();
256
257 private:
258     //! The LJ and charge parameters
259     Params params_;
260     //! The total number of atoms currently stored
261     int numAtoms_;
262
263 public:
264     //! Number of local atoms
265     int natoms_local;
266     //! The format of x (and q), enum
267     int XFormat;
268     //! The format of f, enum
269     int FFormat;
270     //! Do we need to update shift_vec every step?
271     gmx_bool bDynamicBox;
272     //! Shift vectors, copied from t_forcerec
273     gmx::HostVector<gmx::RVec> shift_vec;
274     //! stride for a coordinate in x (usually 3 or 4)
275     int xstride;
276     //! stride for a coordinate in f (usually 3 or 4)
277     int fstride;
278
279 private:
280     //! x and possibly q, size natoms*xstride
281     gmx::HostVector<real> x_;
282
283 public:
284     //! Masks for handling exclusions in the SIMD kernels
285     const SimdMasks simdMasks;
286
287     //! Output data structures, 1 per thread
288     std::vector<nbnxn_atomdata_output_t> out;
289
290     //! Reduction related data
291     //! \{
292     //! Use the flags or operate on all atoms
293     gmx_bool bUseBufferFlags;
294     //! Flags for buffer zeroing+reduc.
295     nbnxn_buffer_flags_t buffer_flags;
296     //! Use tree for force reduction
297     gmx_bool bUseTreeReduce;
298     //! Synchronization step for tree reduce
299     tMPI_Atomic* syncStep;
300     //! \}
301 };
302
303 /*! \brief Copy na rvec elements from x to xnb using nbatFormat, start dest a0,
304  * and fills up to na_round with coordinates that are far away.
305  */
306 void copy_rvec_to_nbat_real(const int* a, int na, int na_round, const rvec* x, int nbatFormat, real* xnb, int a0);
307
308 //! Describes the combination rule in use by this force field
309 enum
310 {
311     enbnxninitcombruleDETECT,
312     enbnxninitcombruleGEOM,
313     enbnxninitcombruleLB,
314     enbnxninitcombruleNONE
315 };
316
317 /*! \brief Initialize the non-bonded atom data structure.
318  *
319  * The enum for nbatXFormat is in the file defining nbnxn_atomdata_t.
320  * Copy the ntypes*ntypes*2 sized nbfp non-bonded parameter list
321  * to the atom data structure.
322  * enbnxninitcombrule sets what combination rule data gets stored in nbat.
323  */
324 void nbnxn_atomdata_init(const gmx::MDLogger&      mdlog,
325                          nbnxn_atomdata_t*         nbat,
326                          Nbnxm::KernelType         kernelType,
327                          int                       enbnxninitcombrule,
328                          int                       ntype,
329                          gmx::ArrayRef<const real> nbfp,
330                          int                       n_energygroups,
331                          int                       nout);
332
333 //! Sets the atomdata after pair search
334 void nbnxn_atomdata_set(nbnxn_atomdata_t*     nbat,
335                         const Nbnxm::GridSet& gridSet,
336                         const t_mdatoms*      mdatoms,
337                         const int*            atinfo);
338
339 //! Copy the shift vectors to nbat
340 void nbnxn_atomdata_copy_shiftvec(gmx_bool dynamic_box, rvec* shift_vec, nbnxn_atomdata_t* nbat);
341
342 /*! \brief Transform coordinates to xbat layout
343  *
344  * Creates a copy of the coordinates buffer using short-range ordering.
345  *
346  * \param[in] gridSet      The grids data.
347  * \param[in] locality     If the transformation should be applied to local or non local coordinates.
348  * \param[in] fillLocal    Tells if the local filler particle coordinates should be zeroed.
349  * \param[in] coordinates  Coordinates in plain rvec format.
350  * \param[in,out] nbat     Data in NBNXM format, used for mapping formats and to locate the output buffer.
351  */
352 void nbnxn_atomdata_copy_x_to_nbat_x(const Nbnxm::GridSet& gridSet,
353                                      gmx::AtomLocality     locality,
354                                      bool                  fillLocal,
355                                      const rvec*           coordinates,
356                                      nbnxn_atomdata_t*     nbat);
357
358 /*! \brief Transform coordinates to xbat layout on GPU
359  *
360  * Creates a GPU copy of the coordinates buffer using short-range ordering.
361  * As input, uses coordinates in plain rvec format in GPU memory.
362  *
363  * \param[in]     gridSet    The grids data.
364  * \param[in]     locality   If the transformation should be applied to local or non local coordinates.
365  * \param[in]     fillLocal  Tells if the local filler particle coordinates should be zeroed.
366  * \param[in,out] gpu_nbv    The NBNXM GPU data structure.
367  * \param[in]     d_x        Coordinates to be copied (in plain rvec format).
368  * \param[in]     xReadyOnDevice   Event synchronizer indicating that the coordinates are ready in the device memory.
369  */
370 void nbnxn_atomdata_x_to_nbat_x_gpu(const Nbnxm::GridSet& gridSet,
371                                     gmx::AtomLocality     locality,
372                                     bool                  fillLocal,
373                                     gmx_nbnxm_gpu_t*      gpu_nbv,
374                                     DeviceBuffer<float>   d_x,
375                                     GpuEventSynchronizer* xReadyOnDevice);
376
377 /*! \brief Add the computed forces to \p f, an internal reduction might be performed as well
378  *
379  * \param[in]  nbat        Atom data in NBNXM format.
380  * \param[in]  locality    If the reduction should be performed on local or non-local atoms.
381  * \param[in]  gridSet     The grids data.
382  * \param[out] totalForce  Buffer to accumulate resulting force
383  */
384 void reduceForces(nbnxn_atomdata_t* nbat, gmx::AtomLocality locality, const Nbnxm::GridSet& gridSet, rvec* totalForce);
385
386 /*! \brief Reduce forces on the GPU
387  *
388  * \param[in]  locality             If the reduction should be performed on local or non-local atoms.
389  * \param[out] totalForcesDevice    Device buffer to accumulate resulting force.
390  * \param[in]  gridSet              The grids data.
391  * \param[in]  pmeForcesDevice      Device buffer with PME forces.
392  * \param[in]  dependencyList       List of synchronizers that represent the dependencies the reduction task needs to sync on.
393  * \param[in]  gpu_nbv              The NBNXM GPU data structure.
394  * \param[in]  useGpuFPmeReduction  Whether PME forces should be added.
395  * \param[in]  accumulateForce      Whether there are usefull data already in the total force buffer.
396  */
397 void reduceForcesGpu(gmx::AtomLocality                          locality,
398                      DeviceBuffer<float>                        totalForcesDevice,
399                      const Nbnxm::GridSet&                      gridSet,
400                      void*                                      pmeForcesDevice,
401                      gmx::ArrayRef<GpuEventSynchronizer* const> dependencyList,
402                      gmx_nbnxm_gpu_t*                           gpu_nbv,
403                      bool                                       useGpuFPmeReduction,
404                      bool                                       accumulateForce);
405
406 //! Add the fshift force stored in nbat to fshift
407 void nbnxn_atomdata_add_nbat_fshift_to_fshift(const nbnxn_atomdata_t& nbat, gmx::ArrayRef<gmx::RVec> fshift);
408
409 //! Get the atom start index and number of atoms for a given locality
410 void nbnxn_get_atom_range(gmx::AtomLocality     atomLocality,
411                           const Nbnxm::GridSet& gridSet,
412                           int*                  atomStart,
413                           int*                  nAtoms);
414 #endif