2 * This file is part of the GROMACS molecular simulation package.
4 * Copyright (c) 2014,2015,2016,2017,2018 by the GROMACS development team.
5 * Copyright (c) 2019,2020,2021, 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.
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.
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.
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.
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.
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.
38 * \brief This file contains declarations for functions needed
39 * internally by the module.
41 * \author Mark Abraham <mark.j.abraham@gmail.com>
42 * \author Berk Hess <hess@kth.se>
43 * \ingroup module_listed_forces
45 #ifndef GMX_LISTED_FORCES_LISTED_INTERNAL_H
46 #define GMX_LISTED_FORCES_LISTED_INTERNAL_H
50 #include "gromacs/math/vectypes.h"
51 #include "gromacs/mdtypes/enerdata.h"
52 #include "gromacs/topology/idef.h"
53 #include "gromacs/topology/ifunc.h"
54 #include "gromacs/utility/alignedallocator.h"
55 #include "gromacs/utility/bitmask.h"
56 #include "gromacs/utility/classhelpers.h"
57 #include "gromacs/utility/enumerationhelpers.h"
59 /* We reduce the force array in blocks of 32 atoms. This is large enough
60 * to not cause overhead and 32*sizeof(rvec) is a multiple of the cache-line
61 * size on all systems.
63 static const int reduction_block_size = 32; /**< Force buffer block size in atoms*/
64 static const int reduction_block_bits = 5; /**< log2(reduction_block_size) */
66 /*! \internal \brief The division of bonded interactions of the threads */
71 WorkDivision(int numThreads) : stride_(numThreads + 1), packedBounds_(F_NRE * stride_) {}
73 //! Sets the bound between threads \p boundIndex-1 and \p boundIndex to \p count
74 void setBound(int functionType, int boundIndex, int count)
76 packedBounds_[functionType * stride_ + boundIndex] = count;
79 //! Returns the bound between threads \p boundIndex-1 and \p boundIndex
80 int bound(int functionType, int boundIndex) const
82 return packedBounds_[functionType * stride_ + boundIndex];
85 //! Returns the last bound
86 int end(int ftype) const { return bound(ftype, stride_ - 1); }
89 //! The stride_ between and size of the entries for a function type
91 //! The bounds stored as a flat array for fast access
92 std::vector<int> packedBounds_;
95 /*! \internal \brief struct with output for bonded forces, used per thread */
99 f_thread_t(int numEnergyGroups);
101 ~f_thread_t() = default;
103 //! Force array pointer, equals fBuffer.data(), needed because rvec4 is not a C++ type
105 //! Force array buffer
106 std::vector<real, gmx::AlignedAllocator<real>> fBuffer;
107 //! Mask for marking which parts of f are filled, working array for constructing mask in bonded_threading_t
108 std::vector<gmx_bitmask_t> mask;
109 //! Number of blocks touched by our thread
111 //! Index to touched blocks
112 std::vector<int> block_index;
114 //! Shift force array, size c_numShiftVectors
115 std::vector<gmx::RVec> fshift;
118 //! Group pair energy data for pairs
119 gmx_grppairener_t grpp;
120 //! Free-energy dV/dl output
121 gmx::EnumerationArray<FreeEnergyPerturbationCouplingType, real> dvdl;
123 GMX_DISALLOW_COPY_MOVE_AND_ASSIGN(f_thread_t);
126 /*! \internal \brief struct contain all data for bonded force threading */
127 struct bonded_threading_t
130 bonded_threading_t(int numThreads, int numEnergyGroups, FILE* fplog);
132 //! Number of threads to be used for bondeds
134 //! Force/energy data per thread, size nthreads, stored in unique_ptr to allow thread local allocation
135 std::vector<std::unique_ptr<f_thread_t>> f_t;
136 //! The number of force blocks to reduce
138 //! Index of size nblock_used into mask
139 std::vector<int> block_index;
140 //! Mask array, one element corresponds to a block of reduction_block_size atoms of the force array, bit corresponding to thread indices set if a thread writes to that block
141 std::vector<gmx_bitmask_t> mask;
142 //! true if we have and thus need to reduce bonded forces
143 bool haveBondeds = false;
144 //! The number of atoms forces are computed for
145 int numAtomsForce = 0;
147 /* There are two different ways to distribute the bonded force calculation
148 * over the threads. We dedice which to use based on the number of threads.
150 //! Maximum thread count for uniform distribution of bondeds over threads
151 int max_nthread_uniform = 0;
153 //! The division of work in the t_list over threads.
154 WorkDivision workDivision;
156 //! Work division for free-energy foreign lambda calculations, always uses 1 thread
157 WorkDivision foreignLambdaWorkDivision;
159 GMX_DISALLOW_COPY_MOVE_AND_ASSIGN(bonded_threading_t);
163 /*! \brief Returns the global topology atom number belonging to local
166 * This function is intended for writing ascii output and returns atom
167 * numbers starting at 1. When global_atom_index=NULL returns i+1.
169 int glatnr(const int* global_atom_index, int i);