Make PBC type enumeration into PbcType enum class
[gromacs.git] / src / gromacs / nbnxm / gridset.cpp
blob1adcff76a67218b481c024f88107ed8ee352144c
1 /*
2 * This file is part of the GROMACS molecular simulation package.
4 * Copyright (c) 2019,2020, 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.
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.
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.
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.
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.
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.
36 /*! \internal \file
38 * \brief
39 * Implements the GridSet class.
41 * \author Berk Hess <hess@kth.se>
42 * \ingroup module_nbnxm
45 #include "gmxpre.h"
47 #include "gridset.h"
49 #include "gromacs/mdlib/gmx_omp_nthreads.h"
50 #include "gromacs/mdlib/updategroupscog.h"
51 #include "gromacs/utility/fatalerror.h"
53 #include "atomdata.h"
55 namespace Nbnxm
58 //! Returns the number of search grids
59 static int numGrids(const GridSet::DomainSetup& domainSetup)
61 int numGrids;
62 if (domainSetup.doTestParticleInsertion)
64 numGrids = 2;
66 else
68 numGrids = 1;
69 for (auto haveDD : domainSetup.haveMultipleDomainsPerDim)
71 if (haveDD)
73 numGrids *= 2;
78 return numGrids;
81 GridSet::DomainSetup::DomainSetup(const PbcType pbcType,
82 const bool doTestParticleInsertion,
83 const ivec* numDDCells,
84 const gmx_domdec_zones_t* ddZones) :
85 pbcType(pbcType),
86 doTestParticleInsertion(doTestParticleInsertion),
87 haveMultipleDomains(numDDCells != nullptr),
88 zones(ddZones)
90 for (int d = 0; d < DIM; d++)
92 haveMultipleDomainsPerDim[d] = (numDDCells != nullptr && (*numDDCells)[d] > 1);
96 GridSet::GridSet(const PbcType pbcType,
97 const bool doTestParticleInsertion,
98 const ivec* numDDCells,
99 const gmx_domdec_zones_t* ddZones,
100 const PairlistType pairlistType,
101 const bool haveFep,
102 const int numThreads,
103 gmx::PinningPolicy pinningPolicy) :
104 domainSetup_(pbcType, doTestParticleInsertion, numDDCells, ddZones),
105 grids_(numGrids(domainSetup_), Grid(pairlistType, haveFep_)),
106 haveFep_(haveFep),
107 numRealAtomsLocal_(0),
108 numRealAtomsTotal_(0),
109 gridWork_(numThreads)
111 clear_mat(box_);
112 changePinningPolicy(&gridSetData_.cells, pinningPolicy);
113 changePinningPolicy(&gridSetData_.atomIndices, pinningPolicy);
116 void GridSet::setLocalAtomOrder()
118 /* Set the atom order for the home cell (index 0) */
119 const Nbnxm::Grid& grid = grids_[0];
121 int atomIndex = 0;
122 for (int cxy = 0; cxy < grid.numColumns(); cxy++)
124 const int numAtoms = grid.numAtomsInColumn(cxy);
125 int cellIndex = grid.firstCellInColumn(cxy) * grid.geometry().numAtomsPerCell;
126 for (int i = 0; i < numAtoms; i++)
128 gridSetData_.atomIndices[cellIndex] = atomIndex;
129 gridSetData_.cells[atomIndex] = cellIndex;
130 atomIndex++;
131 cellIndex++;
136 void GridSet::putOnGrid(const matrix box,
137 const int gridIndex,
138 const rvec lowerCorner,
139 const rvec upperCorner,
140 const gmx::UpdateGroupsCog* updateGroupsCog,
141 const gmx::Range<int> atomRange,
142 real atomDensity,
143 gmx::ArrayRef<const int> atomInfo,
144 gmx::ArrayRef<const gmx::RVec> x,
145 const int numAtomsMoved,
146 const int* move,
147 nbnxn_atomdata_t* nbat)
149 Nbnxm::Grid& grid = grids_[gridIndex];
151 int cellOffset;
152 if (gridIndex == 0)
154 cellOffset = 0;
156 else
158 const Nbnxm::Grid& previousGrid = grids_[gridIndex - 1];
159 cellOffset = previousGrid.atomIndexEnd() / previousGrid.geometry().numAtomsPerCell;
162 const int n = atomRange.size();
164 real maxAtomGroupRadius;
165 if (gridIndex == 0)
167 copy_mat(box, box_);
169 numRealAtomsLocal_ = *atomRange.end() - numAtomsMoved;
170 /* We assume that nbnxn_put_on_grid is called first
171 * for the local atoms (gridIndex=0).
173 numRealAtomsTotal_ = *atomRange.end() - numAtomsMoved;
175 maxAtomGroupRadius = (updateGroupsCog ? updateGroupsCog->maxUpdateGroupRadius() : 0);
177 if (debug)
179 fprintf(debug, "natoms_local = %5d atom_density = %5.1f\n", numRealAtomsLocal_, atomDensity);
182 else
184 const Nbnxm::Grid::Dimensions& dimsGrid0 = grids_[0].dimensions();
185 atomDensity = dimsGrid0.atomDensity;
186 maxAtomGroupRadius = dimsGrid0.maxAtomGroupRadius;
188 numRealAtomsTotal_ = std::max(numRealAtomsTotal_, *atomRange.end());
191 /* We always use the home zone (grid[0]) for setting the cell size,
192 * since determining densities for non-local zones is difficult.
194 const int ddZone = (domainSetup_.doTestParticleInsertion ? 0 : gridIndex);
195 // grid data used in GPU transfers inherits the gridset pinning policy
196 auto pinPolicy = gridSetData_.cells.get_allocator().pinningPolicy();
197 grid.setDimensions(ddZone, n - numAtomsMoved, lowerCorner, upperCorner, atomDensity,
198 maxAtomGroupRadius, haveFep_, pinPolicy);
200 for (GridWork& work : gridWork_)
202 work.numAtomsPerColumn.resize(grid.numColumns() + 1);
205 /* Make space for the new cell indices */
206 gridSetData_.cells.resize(*atomRange.end());
208 const int nthread = gmx_omp_nthreads_get(emntPairsearch);
209 GMX_ASSERT(nthread > 0, "We expect the OpenMP thread count to be set");
211 #pragma omp parallel for num_threads(nthread) schedule(static)
212 for (int thread = 0; thread < nthread; thread++)
216 Grid::calcColumnIndices(grid.dimensions(), updateGroupsCog, atomRange, x, ddZone, move, thread,
217 nthread, gridSetData_.cells, gridWork_[thread].numAtomsPerColumn);
219 GMX_CATCH_ALL_AND_EXIT_WITH_FATAL_ERROR
222 /* Copy the already computed cell indices to the grid and sort, when needed */
223 grid.setCellIndices(ddZone, cellOffset, &gridSetData_, gridWork_, atomRange, atomInfo.data(), x,
224 numAtomsMoved, nbat);
226 if (gridIndex == 0)
228 nbat->natoms_local = nbat->numAtoms();
230 if (gridIndex == gmx::ssize(grids_) - 1)
232 /* We are done setting up all grids, we can resize the force buffers */
233 nbat->resizeForceBuffers();
236 int maxNumColumns = 0;
237 for (int i = 0; i <= gridIndex; i++)
239 maxNumColumns = std::max(maxNumColumns, grids_[i].numColumns());
241 setNumColumnsMax(maxNumColumns);
244 } // namespace Nbnxm