1 /* 2 * This file is part of the GROMACS molecular simulation package. 3 * 4 * Copyright (c) 2014,2015,2016,2017,2018 by the GROMACS development team. 5 * Copyright (c) 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 /*! \internal \file 37 * 38 * \brief This file contains declarations for functions needed 39 * internally by the module. 40 * 41 * \author Mark Abraham <mark.j.abraham@gmail.com> 42 * \author Berk Hess <hess@kth.se> 43 * \ingroup module_listed_forces 44 */ 45 #ifndef GMX_LISTED_FORCES_LISTED_INTERNAL_H 46 #define GMX_LISTED_FORCES_LISTED_INTERNAL_H 47 48 #include <memory> 49 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 58 /* We reduce the force array in blocks of 32 atoms. This is large enough 59 * to not cause overhead and 32*sizeof(rvec) is a multiple of the cache-line 60 * size on all systems. 61 */ 62 static const int reduction_block_size = 32; /**< Force buffer block size in atoms*/ 63 static const int reduction_block_bits = 5; /**< log2(reduction_block_size) */ 64 65 /*! \internal \brief The division of bonded interactions of the threads */ 66 class WorkDivision 67 { 68 public: 69 //! Constructor WorkDivision(int numThreads)70 WorkDivision(int numThreads) : stride_(numThreads + 1), packedBounds_(F_NRE * stride_) {} 71 72 //! Sets the bound between threads \p boundIndex-1 and \p boundIndex to \p count setBound(int functionType,int boundIndex,int count)73 void setBound(int functionType, int boundIndex, int count) 74 { 75 packedBounds_[functionType * stride_ + boundIndex] = count; 76 } 77 78 //! Returns the bound between threads \p boundIndex-1 and \p boundIndex bound(int functionType,int boundIndex)79 int bound(int functionType, int boundIndex) const 80 { 81 return packedBounds_[functionType * stride_ + boundIndex]; 82 } 83 84 //! Returns the last bound end(int ftype)85 int end(int ftype) const { return bound(ftype, stride_ - 1); } 86 87 private: 88 //! The stride_ between and size of the entries for a function type 89 int stride_; 90 //! The bounds stored as a flat array for fast access 91 std::vector<int> packedBounds_; 92 }; 93 94 /*! \internal \brief struct with output for bonded forces, used per thread */ 95 struct f_thread_t 96 { 97 //! Constructor 98 f_thread_t(int numEnergyGroups); 99 100 ~f_thread_t() = default; 101 102 //! Force array pointer, equals fBuffer.data(), needed because rvec4 is not a C++ type 103 rvec4* f = nullptr; 104 //! Force array buffer 105 std::vector<real, gmx::AlignedAllocator<real>> fBuffer; 106 //! Mask for marking which parts of f are filled, working array for constructing mask in bonded_threading_t 107 std::vector<gmx_bitmask_t> mask; 108 //! Number of blocks touched by our thread 109 int nblock_used = 0; 110 //! Index to touched blocks 111 std::vector<int> block_index; 112 113 //! Shift force array, size SHIFTS 114 std::vector<gmx::RVec> fshift; 115 //! Energy array 116 real ener[F_NRE]; 117 //! Group pair energy data for pairs 118 gmx_grppairener_t grpp; 119 //! Free-energy dV/dl output 120 real dvdl[efptNR]; 121 122 GMX_DISALLOW_COPY_MOVE_AND_ASSIGN(f_thread_t); 123 }; 124 125 /*! \internal \brief struct contain all data for bonded force threading */ 126 struct bonded_threading_t 127 { 128 //! Constructor 129 bonded_threading_t(int numThreads, int numEnergyGroups, FILE* fplog); 130 131 //! Number of threads to be used for bondeds 132 int nthreads = 0; 133 //! Force/energy data per thread, size nthreads, stored in unique_ptr to allow thread local allocation 134 std::vector<std::unique_ptr<f_thread_t>> f_t; 135 //! The number of force blocks to reduce 136 int nblock_used = 0; 137 //! Index of size nblock_used into mask 138 std::vector<int> block_index; 139 //! 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 140 std::vector<gmx_bitmask_t> mask; 141 //! true if we have and thus need to reduce bonded forces 142 bool haveBondeds = false; 143 //! The number of atoms forces are computed for 144 int numAtomsForce = 0; 145 146 /* There are two different ways to distribute the bonded force calculation 147 * over the threads. We dedice which to use based on the number of threads. 148 */ 149 //! Maximum thread count for uniform distribution of bondeds over threads 150 int max_nthread_uniform = 0; 151 152 //! The division of work in the t_list over threads. 153 WorkDivision workDivision; 154 155 //! Work division for free-energy foreign lambda calculations, always uses 1 thread 156 WorkDivision foreignLambdaWorkDivision; 157 158 GMX_DISALLOW_COPY_MOVE_AND_ASSIGN(bonded_threading_t); 159 }; 160 161 162 /*! \brief Returns the global topology atom number belonging to local 163 * atom index i. 164 * 165 * This function is intended for writing ascii output and returns atom 166 * numbers starting at 1. When global_atom_index=NULL returns i+1. 167 */ 168 int glatnr(const int* global_atom_index, int i); 169 170 #endif 171